d3d12: Rework TextureCopySplitter to compute in blocks
- Now that TextureCopySplitter has been updated to use strong types,
rework it to compute in blocks.
- Change TextureCopyResource::CopyInfo to store values in blocks, rather
than texels, and update RecordBufferTextureCopyFromSplits to convert
these to texels at the last moment before adding to the D3D12 command
list.
- Fix CopySplitTest.TextureX and TextureY to skip texel values that are
not multiples of the block size, as required by the spec.
Bug: 424536624
Change-Id: I33ac1dda9b132ddb940d9d955ca7dd8d223352e2
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/247935
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn/native/BlockInfo.h b/src/dawn/native/BlockInfo.h
index 33c17c8..d199269 100644
--- a/src/dawn/native/BlockInfo.h
+++ b/src/dawn/native/BlockInfo.h
@@ -33,24 +33,31 @@
namespace dawn::native {
-// Strong types for texel and block counts
+// Strong types for texel and block counts.
+// These are used to avoid computation errors that occur when using regular integers
+// for texel and block values, and mixing them up in computations, particularly for block
+// sizes greater than 1x1.
+// By using strong types, we cannot mix these two types in computations, and must use
+// conversion functions provided in TypedTexelBlockInfo.
+
// TexelCount and BlockCount are uint64_t, not uint32_t, because as typed
// integers, they do not participate in type promotion to uint64_t, which
// is being relied on for computing buffer offsets and such.
using TexelCount = dawn::TypedInteger<struct TexelCountTag, uint64_t>;
using BlockCount = dawn::TypedInteger<struct BlockCountTag, uint64_t>;
-// Strong type version of Origin3D
+// Strong type version of Origin3D, which is always in texel space
struct TexelOrigin3D {
TexelCount x{0};
TexelCount y{0};
TexelCount z{0};
- // Default constructor
- TexelOrigin3D() = default;
-
// Construct from input values
- TexelOrigin3D(TexelCount x, TexelCount y, TexelCount z) : x(x), y(y), z(z) {}
+ // NOLINTNEXTLINE: allow implicit constructor
+ TexelOrigin3D(TexelCount x = TexelCount{0},
+ TexelCount y = TexelCount{0},
+ TexelCount z = TexelCount{0})
+ : x(x), y(y), z(z) {}
// Implicitly convert from Origin3D as Origin3D is always in texel space
// NOLINTNEXTLINE: allow implicit constructor
@@ -62,7 +69,21 @@
}
};
-// Strong type version of Extent3D
+// Stores an origin in block space
+struct BlockOrigin3D {
+ BlockCount x{0};
+ BlockCount y{0};
+ BlockCount z{0};
+
+ // Construct from input values
+ // NOLINTNEXTLINE: allow implicit constructor
+ BlockOrigin3D(BlockCount x = BlockCount{0},
+ BlockCount y = BlockCount{0},
+ BlockCount z = BlockCount{0})
+ : x(x), y(y), z(z) {}
+};
+
+// Strong type version of Extent3D.
struct TexelExtent3D {
TexelCount width;
TexelCount height{1};
@@ -72,7 +93,10 @@
TexelExtent3D() = default;
// Construct from input values
- TexelExtent3D(TexelCount width, TexelCount height, TexelCount depthOrArrayLayers)
+ // NOLINTNEXTLINE: allow implicit constructor
+ TexelExtent3D(TexelCount width,
+ TexelCount height = TexelCount{1},
+ TexelCount depthOrArrayLayers = TexelCount{1})
: width(width), height(height), depthOrArrayLayers(depthOrArrayLayers) {}
// Implicitly convert from Extent3D as Extent3D is always in texel space
@@ -87,6 +111,23 @@
}
};
+// Stores an extent in block space
+struct BlockExtent3D {
+ BlockCount width;
+ BlockCount height{1};
+ BlockCount depthOrArrayLayers{1};
+
+ // Default constructor
+ BlockExtent3D() = default;
+
+ // Construct from input values
+ // NOLINTNEXTLINE: allow implicit constructor
+ BlockExtent3D(BlockCount width,
+ BlockCount height = BlockCount{1},
+ BlockCount depthOrArrayLayers = BlockCount{1})
+ : width(width), height(height), depthOrArrayLayers(depthOrArrayLayers) {}
+};
+
// Strong type version of TexelBlockInfo that stores the dimensions of the block
// as TexelCounts, and provides conversion functions between texels, blocks, and bytes.
struct TypedTexelBlockInfo {
@@ -118,12 +159,14 @@
// Convert texel height to block height
BlockCount ToBlockHeight(TexelCount value) const {
- return BlockCount{static_cast<uint64_t>((value + height - TexelCount{1}) / height)};
+ DAWN_ASSERT(value % height == TexelCount{0});
+ return BlockCount{static_cast<uint64_t>(value / height)};
}
// Convert from texel width to block width
BlockCount ToBlockWidth(TexelCount value) const {
- return BlockCount{static_cast<uint64_t>((value + width - TexelCount{1}) / width)};
+ DAWN_ASSERT(value % width == TexelCount{0});
+ return BlockCount{static_cast<uint64_t>(value / width)};
}
// Convert from texel depth to block depth
@@ -149,6 +192,28 @@
// 'depth'
return TexelCount{static_cast<uint64_t>(value)};
}
+
+ // Convert from TexelOrigin3D to BlockOrigin3D
+ BlockOrigin3D ToBlock(const TexelOrigin3D& origin) {
+ return {ToBlockWidth(origin.x), ToBlockHeight(origin.y), ToBlockDepth(origin.z)};
+ }
+
+ // Convert from TexelExtent3D to BlockExtent3D
+ BlockExtent3D ToBlock(const TexelExtent3D& extent) {
+ return {ToBlockWidth(extent.width), ToBlockHeight(extent.height),
+ ToBlockDepth(extent.depthOrArrayLayers)};
+ }
+
+ // Convert from BlockOrigin3D to TexelOrigin3D
+ TexelOrigin3D ToTexel(const BlockOrigin3D& origin) {
+ return {ToTexelWidth(origin.x), ToTexelHeight(origin.y), ToTexelDepth(origin.z)};
+ }
+
+ // Convert from BlockExtent3D to TexelExtent3D
+ TexelExtent3D ToTexel(const BlockExtent3D& extent) {
+ return {ToTexelWidth(extent.width), ToTexelHeight(extent.height),
+ ToTexelDepth(extent.depthOrArrayLayers)};
+ }
};
} // namespace dawn::native
diff --git a/src/dawn/native/d3d12/TextureCopySplitter.cpp b/src/dawn/native/d3d12/TextureCopySplitter.cpp
index 2ec4d5d..e6a9437 100644
--- a/src/dawn/native/d3d12/TextureCopySplitter.cpp
+++ b/src/dawn/native/d3d12/TextureCopySplitter.cpp
@@ -34,27 +34,23 @@
namespace dawn::native::d3d12 {
namespace {
-// TODO(424536624): Return a BlockOrigin3D
-TexelOrigin3D ComputeTexelOffsets(const TypedTexelBlockInfo& blockInfo,
+BlockOrigin3D ComputeBlockOffsets(const TypedTexelBlockInfo& blockInfo,
uint32_t offset,
BlockCount blocksPerRow) {
DAWN_ASSERT(blocksPerRow != BlockCount{0});
BlockCount offsetInBlocks = blockInfo.BytesToBlocks(offset);
BlockCount blockOffsetX = offsetInBlocks % blocksPerRow;
BlockCount blockOffsetY = offsetInBlocks / blocksPerRow;
- return {blockInfo.ToTexelWidth(blockOffsetX), blockInfo.ToTexelHeight(blockOffsetY),
- TexelCount{0}};
+ return {blockOffsetX, blockOffsetY, BlockCount{0}};
}
uint64_t OffsetToFirstCopiedTexel(const TypedTexelBlockInfo& blockInfo,
BlockCount blocksPerRow,
uint64_t alignedOffset,
- TexelOrigin3D bufferOffset) {
- DAWN_ASSERT(bufferOffset.z == TexelCount{0});
-
+ BlockOrigin3D bufferOffset) {
+ DAWN_ASSERT(bufferOffset.z == BlockCount{0});
uint64_t offset =
- alignedOffset + blockInfo.ToBytes(blockInfo.ToBlockWidth(bufferOffset.x) +
- blocksPerRow * blockInfo.ToBlockHeight(bufferOffset.y));
+ alignedOffset + blockInfo.ToBytes(bufferOffset.x + blocksPerRow * bufferOffset.y);
return offset;
}
@@ -74,11 +70,10 @@
const TexelBlockInfo& blockInfo_in,
uint64_t offset,
uint32_t bytesPerRow_in) {
- // TODO(424536624): Rework this function to compute in blocks, then convert to texels
- auto origin = TexelOrigin3D(origin_in);
- auto copySize = TexelExtent3D(copySize_in);
- auto blockInfo = TypedTexelBlockInfo(blockInfo_in);
- auto blocksPerRow = blockInfo.BytesToBlocks(bytesPerRow_in);
+ TypedTexelBlockInfo blockInfo{blockInfo_in};
+ BlockOrigin3D origin = blockInfo.ToBlock(origin_in);
+ BlockExtent3D copySize = blockInfo.ToBlock(copySize_in);
+ BlockCount blocksPerRow = blockInfo.BytesToBlocks(bytesPerRow_in);
TextureCopySubresource copy;
@@ -90,7 +85,7 @@
// without further translation.
if (offset == alignedOffset) {
TextureCopySubresource::CopyInfo* copyInfo = copy.AddCopy();
- copyInfo->bufferOffset = TexelOrigin3D{{0, 0, 0}};
+ copyInfo->bufferOffset = {}; // 0,0,0
copyInfo->textureOffset = origin;
copyInfo->copySize = copySize;
copyInfo->alignedOffset = alignedOffset;
@@ -115,20 +110,20 @@
// |+++++~~~~~~~~~~~|
// |<---row pitch-->|
//
- // The X and Y offsets calculated in ComputeTexelOffsets can be visualized like this:
+ // The X and Y offsets calculated in ComputeBlockOffsets can be visualized like this:
// |YYYYYYYYYYYYYYYY|
// |XXXXXX++++++++++|
// |++++++++++++++++|
// |++++++~~~~~~~~~~|
// |<---row pitch-->|
- TexelOrigin3D texelOffset =
- ComputeTexelOffsets(blockInfo, static_cast<uint32_t>(offset - alignedOffset), blocksPerRow);
+ BlockOrigin3D blockOffset =
+ ComputeBlockOffsets(blockInfo, static_cast<uint32_t>(offset - alignedOffset), blocksPerRow);
- DAWN_ASSERT(texelOffset.y <= blockInfo.height);
- DAWN_ASSERT(texelOffset.z == TexelCount{0});
+ DAWN_ASSERT(blockOffset.y <= BlockCount{1});
+ DAWN_ASSERT(blockOffset.z == BlockCount{0});
- BlockCount copyBlocksPerRowPitch = blockInfo.ToBlockWidth(copySize.width);
- BlockCount blockOffsetInRowPitch = blockInfo.ToBlockWidth(texelOffset.x);
+ BlockCount copyBlocksPerRowPitch = copySize.width;
+ BlockCount blockOffsetInRowPitch = blockOffset.x;
if (copyBlocksPerRowPitch + blockOffsetInRowPitch <= blocksPerRow) {
// The region's rows fit inside the bytes per row. In this case, extend the width of the
// PlacedFootprint and copy the buffer with an offset location
@@ -154,11 +149,11 @@
// |----------------------------------|
TextureCopySubresource::CopyInfo* copyInfo = copy.AddCopy();
- copyInfo->bufferOffset = texelOffset;
+ copyInfo->bufferOffset = blockOffset;
copyInfo->textureOffset = origin;
copyInfo->copySize = copySize;
copyInfo->alignedOffset = alignedOffset;
- copyInfo->bufferSize = {copySize.width + texelOffset.x, copySize.height + texelOffset.y,
+ copyInfo->bufferSize = {copySize.width + blockOffset.x, copySize.height + blockOffset.y,
copySize.depthOrArrayLayers};
return copy;
}
@@ -199,36 +194,35 @@
// Copy 0
DAWN_ASSERT(blocksPerRow > blockOffsetInRowPitch);
- const TexelCount texelsPerRow = blockInfo.ToTexelWidth(blocksPerRow);
- const TexelExtent3D copySize0 = {texelsPerRow - texelOffset.x, copySize.height,
+ const BlockExtent3D copySize0 = {blocksPerRow - blockOffset.x, copySize.height,
copySize.depthOrArrayLayers};
+
TextureCopySubresource::CopyInfo* copyInfo0 = copy.AddCopy();
- copyInfo0->bufferOffset = texelOffset;
+ copyInfo0->bufferOffset = blockOffset;
copyInfo0->textureOffset = origin;
copyInfo0->copySize = copySize0;
copyInfo0->alignedOffset = alignedOffset;
- copyInfo0->bufferSize = {texelsPerRow, copySize.height + texelOffset.y,
+ copyInfo0->bufferSize = {blocksPerRow, copySize.height + blockOffset.y,
copySize.depthOrArrayLayers};
// Copy 1
- const uint64_t offsetForCopy1 =
- offset + blockInfo.ToBytes(blockInfo.ToBlockWidth(copySize0.width));
+ const uint64_t offsetForCopy1 = offset + blockInfo.ToBytes(copySize0.width);
const uint64_t alignedOffsetForCopy1 = AlignDownForDataPlacement(offsetForCopy1);
- const TexelOrigin3D texelOffsetForCopy1 = ComputeTexelOffsets(
+ const BlockOrigin3D blockOffsetForCopy1 = ComputeBlockOffsets(
blockInfo, static_cast<uint32_t>(offsetForCopy1 - alignedOffsetForCopy1), blocksPerRow);
- DAWN_ASSERT(texelOffsetForCopy1.y <= blockInfo.height);
- DAWN_ASSERT(texelOffsetForCopy1.z == TexelCount{0});
+ DAWN_ASSERT(blockOffsetForCopy1.y <= BlockCount{1});
+ DAWN_ASSERT(blockOffsetForCopy1.z == BlockCount{0});
- const TexelOrigin3D textureOffset1 = {origin.x + copySize0.width, origin.y, origin.z};
+ const BlockOrigin3D textureOffset1 = {origin.x + copySize0.width, origin.y, origin.z};
DAWN_ASSERT(copySize.width > copySize0.width);
- const TexelExtent3D copySize1 = {copySize.width - copySize0.width, copySize.height,
+ const BlockExtent3D copySize1 = {copySize.width - copySize0.width, copySize.height,
copySize.depthOrArrayLayers};
- const TexelOrigin3D bufferOffset1 = texelOffsetForCopy1;
- const TexelExtent3D bufferSize1 = {copySize1.width + texelOffsetForCopy1.x,
- copySize.height + texelOffsetForCopy1.y,
+ const BlockOrigin3D bufferOffset1 = blockOffsetForCopy1;
+ const BlockExtent3D bufferSize1 = {copySize1.width + blockOffsetForCopy1.x,
+ copySize.height + blockOffsetForCopy1.y,
copySize.depthOrArrayLayers};
TextureCopySubresource::CopyInfo* copyInfo1 = copy.AddCopy();
@@ -293,20 +287,13 @@
}
void Recompute3DTextureCopyRegionWithEmptyFirstRowAndEvenCopyHeight(
- Origin3D origin_in,
- Extent3D copySize_in,
- const TexelBlockInfo& blockInfo_in,
- uint32_t bytesPerRow_in,
- uint32_t rowsPerImage_in,
+ BlockOrigin3D origin,
+ BlockExtent3D copySize,
+ const TypedTexelBlockInfo& blockInfo,
+ BlockCount blocksPerRow,
+ BlockCount rowsPerImage,
TextureCopySubresource& copy,
uint32_t i) {
- // TODO(424536624): Rework this function to compute in blocks, then convert to texels
- auto origin = TexelOrigin3D(origin_in);
- auto copySize = TexelExtent3D(copySize_in);
- auto blockInfo = TypedTexelBlockInfo(blockInfo_in);
- auto rowsPerImage = BlockCount(rowsPerImage_in);
- auto blocksPerRow = blockInfo.BytesToBlocks(bytesPerRow_in);
-
// 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,
@@ -399,20 +386,20 @@
// Copy 0: copy copySize0.height - 1 rows
TextureCopySubresource::CopyInfo& copy0 = copy.copies[i];
- copy0.copySize.height = copySize.height - blockInfo.height;
- copy0.bufferSize.height = blockInfo.ToTexelHeight(rowsPerImage); // rowsPerImageInTexels
+ copy0.copySize.height = copySize.height - BlockCount{1};
+ copy0.bufferSize.height = rowsPerImage;
// 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 = copy1->alignedOffset + 2 * blockInfo.ToBytes(blocksPerRow);
- copy1->textureOffset.y += copySize.height - blockInfo.height;
+ copy1->textureOffset.y += copySize.height - BlockCount{1};
// Offset two rows from the copy height for bufferOffset1 (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 - TexelCount{2} * blockInfo.height;
- copy1->copySize.height = blockInfo.height;
+ copy1->bufferOffset.y = copySize.height - BlockCount{2};
+ copy1->copySize.height = BlockCount{1};
copy1->copySize.depthOrArrayLayers--;
copy1->bufferSize.depthOrArrayLayers--;
@@ -423,12 +410,11 @@
offsetForCopy0 +
blockInfo.ToBytes(
blocksPerRow *
- (blockInfo.ToBlockHeight(copy0.copySize.height) +
- rowsPerImage * (blockInfo.ToBlockDepth(copySize.depthOrArrayLayers) - BlockCount{1})));
+ (copy0.copySize.height + rowsPerImage * (copySize.depthOrArrayLayers - BlockCount{1})));
uint64_t alignedOffsetForLastRowOfLastImage =
AlignDownForDataPlacement(offsetForLastRowOfLastImage);
- TexelOrigin3D texelOffsetForLastRowOfLastImage = ComputeTexelOffsets(
+ BlockOrigin3D blockOffsetForLastRowOfLastImage = ComputeBlockOffsets(
blockInfo,
static_cast<uint32_t>(offsetForLastRowOfLastImage - alignedOffsetForLastRowOfLastImage),
blocksPerRow);
@@ -436,27 +422,22 @@
TextureCopySubresource::CopyInfo* copy2 = copy.AddCopy();
copy2->alignedOffset = alignedOffsetForLastRowOfLastImage;
copy2->textureOffset = copy1->textureOffset;
- copy2->textureOffset.z = origin.z + copySize.depthOrArrayLayers - TexelCount{1};
+ copy2->textureOffset.z = origin.z + copySize.depthOrArrayLayers - BlockCount{1};
copy2->copySize = copy1->copySize;
- copy2->copySize.depthOrArrayLayers = TexelCount{1};
- copy2->bufferOffset = texelOffsetForLastRowOfLastImage;
+ copy2->copySize.depthOrArrayLayers = BlockCount{1};
+ copy2->bufferOffset = blockOffsetForLastRowOfLastImage;
copy2->bufferSize.width = copy1->bufferSize.width;
- DAWN_ASSERT(copy2->copySize.height == blockInfo.height);
+ DAWN_ASSERT(copy2->copySize.height == BlockCount{1});
copy2->bufferSize.height = copy2->bufferOffset.y + copy2->copySize.height;
- copy2->bufferSize.depthOrArrayLayers = TexelCount{1};
+ copy2->bufferSize.depthOrArrayLayers = BlockCount{1};
}
void Recompute3DTextureCopyRegionWithEmptyFirstRowAndOddCopyHeight(
- Extent3D copySize_in,
- const TexelBlockInfo& blockInfo_in,
- uint32_t bytesPerRow_in,
+ BlockExtent3D copySize,
+ const TypedTexelBlockInfo& blockInfo,
+ BlockCount blocksPerRow,
TextureCopySubresource& copy,
uint32_t i) {
- // TODO(424536624): Rework this function to compute in blocks, then convert to texels
- auto copySize = TexelExtent3D(copySize_in);
- auto blockInfo = TypedTexelBlockInfo(blockInfo_in);
- auto blocksPerRow = blockInfo.BytesToBlocks(bytesPerRow_in);
-
// 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.
@@ -469,27 +450,26 @@
// Copy 0: copy the first depth slice (image 0)
TextureCopySubresource::CopyInfo& copy0 = copy.copies[i];
- copy0.copySize.depthOrArrayLayers = TexelCount{1};
- const TexelCount kBufferDepth0 = TexelCount{1};
+ copy0.copySize.depthOrArrayLayers = BlockCount{1};
+ const BlockCount kBufferDepth0 = BlockCount{1};
copy0.bufferSize.depthOrArrayLayers = kBufferDepth0;
// Copy 1: copy the rest depth slices in one shot
TextureCopySubresource::CopyInfo* copy1 = copy.AddCopy();
*copy1 = copy0;
- DAWN_ASSERT(blockInfo.ToBlockHeight(copySize.height) % BlockCount{2} == BlockCount{1});
- copy1->alignedOffset += blockInfo.ToBytes(
- (blockInfo.ToBlockHeight(copySize.height) + BlockCount{1}) * blocksPerRow);
+ DAWN_ASSERT(copySize.height % BlockCount{2} == BlockCount{1});
+ copy1->alignedOffset += blockInfo.ToBytes((copySize.height + BlockCount{1}) * blocksPerRow);
DAWN_ASSERT(copy1->alignedOffset % D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT == 0);
// textureOffset1.z should add one because the first slice has already been copied in copy0.
copy1->textureOffset.z++;
// bufferOffset1.y should be 0 because we skipped the first depth slice and there is no empty
// row in this copy region.
- copy1->bufferOffset.y = TexelCount{0};
+ copy1->bufferOffset.y = BlockCount{0};
copy1->copySize.height = copySize.height;
- copy1->copySize.depthOrArrayLayers = copySize.depthOrArrayLayers - TexelCount{1};
+ copy1->copySize.depthOrArrayLayers = copySize.depthOrArrayLayers - BlockCount{1};
copy1->bufferSize.height = copySize.height;
- copy1->bufferSize.depthOrArrayLayers = copySize.depthOrArrayLayers - TexelCount{1};
+ copy1->bufferSize.depthOrArrayLayers = copySize.depthOrArrayLayers - BlockCount{1};
}
TextureCopySubresource Compute3DTextureCopySplits(Origin3D origin_in,
@@ -498,11 +478,11 @@
uint64_t offset,
uint32_t bytesPerRow,
uint32_t rowsPerImage_in) {
- // TODO(424536624): Rework this function to compute in blocks, then convert to texels
- auto origin = TexelOrigin3D(origin_in);
- auto copySize = TexelExtent3D(copySize_in);
- auto blockInfo = TypedTexelBlockInfo(blockInfo_in);
- auto rowsPerImage = BlockCount(rowsPerImage_in);
+ TypedTexelBlockInfo blockInfo{blockInfo_in};
+ BlockOrigin3D origin = blockInfo.ToBlock(origin_in);
+ BlockExtent3D copySize = blockInfo.ToBlock(copySize_in);
+ BlockCount blocksPerRow = blockInfo.BytesToBlocks(bytesPerRow);
+ BlockCount rowsPerImage{rowsPerImage_in};
// To compute the copy region(s) for 3D textures, we call Compute2DTextureCopySubresource
// and get copy region(s) for the first slice of the copy, then extend to all depth slices
@@ -518,67 +498,64 @@
// Call Compute2DTextureCopySubresource and get copy regions. This function has already
// forwarded "copySize.depthOrArrayLayers" to all depth slices.
- TextureCopySubresource copySubresource =
- Compute2DTextureCopySubresource(origin.ToOrigin3D(), copySize.ToExtent3D(),
- blockInfo.ToTexelBlockInfo(), offset, bytesPerRow);
+ TextureCopySubresource copySubresource = Compute2DTextureCopySubresource(
+ blockInfo.ToTexel(origin).ToOrigin3D(), blockInfo.ToTexel(copySize).ToExtent3D(),
+ blockInfo.ToTexelBlockInfo(), offset, bytesPerRow);
DAWN_ASSERT(copySubresource.count <= 2);
// If copySize.depthOrArrayLayers is 1, we can return copySubresource. Because we don't need to
// extend the copy region(s) to other depth slice(s).
- if (copySize.depthOrArrayLayers == TexelCount{1}) {
+ if (copySize.depthOrArrayLayers == BlockCount{1}) {
return copySubresource;
}
- TexelCount rowsPerImageInTexels = blockInfo.ToTexelHeight(rowsPerImage);
// The copy region(s) generated by Compute2DTextureCopySubresource might be incorrect.
// However, we may append a couple more copy regions in the for loop below. We don't need
// to revise these new added copy regions.
uint32_t originalCopyCount = copySubresource.count;
for (uint32_t i = 0; i < originalCopyCount; ++i) {
// There can be one empty row at most in a copy region.
- TexelCount bufferHeight = copySubresource.copies[i].bufferSize.height;
- DAWN_ASSERT(bufferHeight <= rowsPerImageInTexels + blockInfo.height);
+ BlockCount bufferHeight = copySubresource.copies[i].bufferSize.height;
+ DAWN_ASSERT(bufferHeight <= rowsPerImage + BlockCount{1});
- if (bufferHeight == rowsPerImageInTexels) {
- // If the copy region's bufferHeight equals to rowsPerImageInTexels, we can use this
+ if (bufferHeight == rowsPerImage) {
+ // If the copy region's bufferHeight equals to rowsPerImage, we can use this
// copy region without any modification.
continue;
}
- if (bufferHeight < rowsPerImageInTexels) {
- // If we are copying multiple depth slices, we should skip rowsPerImageInTexels rows for
+ if (bufferHeight < rowsPerImage) {
+ // If we are copying multiple depth slices, we should skip rowsPerImage rows for
// each slice even though we only copy partial rows in each slice sometimes.
- copySubresource.copies[i].bufferSize.height = rowsPerImageInTexels;
+ copySubresource.copies[i].bufferSize.height = rowsPerImage;
} else {
- // bufferHeight > rowsPerImageInTexels. There is an empty row in this copy region due to
+ // bufferHeight > rowsPerImage. There is an empty row in this copy region due to
// alignment adjustment.
// bytesPerRow is definitely 256, and it is definitely a full copy on height.
- // Otherwise, bufferHeight won't be greater than rowsPerImageInTexels and there won't be
+ // Otherwise, bufferHeight won't be greater than rowsPerImage and there won't be
// an empty row at the beginning of this copy region.
DAWN_ASSERT(bytesPerRow == D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);
- DAWN_ASSERT(copySize.height == rowsPerImageInTexels);
+ DAWN_ASSERT(copySize.height == rowsPerImage);
- const BlockCount copyHeightInBlocks = blockInfo.ToBlockHeight(copySize.height);
- if (static_cast<uint32_t>(copyHeightInBlocks) % 2 == 0) {
- // If copyHeightInBlocks is even and there is an empty row at the beginning of the
+ const BlockCount copyHeight = copySize.height;
+ if (static_cast<uint32_t>(copyHeight) % 2 == 0) {
+ // If copyHeight is even and there is an empty row at the beginning of the
// first slice of the copy region, the offset of all depth slices will never be
// aligned to D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT (512) and there is always
// an empty row at each depth slice. We need a totally different approach to
// split the copy region.
Recompute3DTextureCopyRegionWithEmptyFirstRowAndEvenCopyHeight(
- origin.ToOrigin3D(), copySize.ToExtent3D(), blockInfo.ToTexelBlockInfo(),
- bytesPerRow, static_cast<uint32_t>(rowsPerImage), copySubresource, i);
+ origin, copySize, blockInfo, blocksPerRow, rowsPerImage, copySubresource, i);
} else {
- // If copyHeightInBlocks is odd and there is an empty row at the beginning of the
+ // If copyHeight 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:
// copy0 to copy the first slice, copy1 to copy the rest slices because the
// 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.ToExtent3D(), blockInfo.ToTexelBlockInfo(), bytesPerRow,
- copySubresource, i);
+ copySize, blockInfo, blocksPerRow, copySubresource, i);
}
}
}
@@ -592,10 +569,9 @@
const TexelBlockInfo& blockInfo_in,
uint64_t offset,
uint32_t /*bytesPerRow*/) {
- // TODO(424536624): Rework this function to compute in blocks, then convert to texels
- auto origin = TexelOrigin3D(origin_in);
- auto copySize = TexelExtent3D(copySize_in);
-
+ TypedTexelBlockInfo blockInfo{blockInfo_in};
+ BlockOrigin3D origin = blockInfo.ToBlock(origin_in);
+ BlockExtent3D copySize = blockInfo.ToBlock(copySize_in);
TextureCopySubresource copy;
auto* copyInfo = copy.AddCopy();
@@ -611,11 +587,11 @@
// |++++++++++++++++++++++| | | |
// |<-----CopyWidth------>| |----------|
//
- copyInfo->textureOffset = {origin.x, origin.y, TexelCount{0}};
- copyInfo->bufferOffset = TexelOrigin3D{{0, 0, 0}};
- copyInfo->copySize = {copySize.width, copySize.height, TexelCount{1}};
+ copyInfo->textureOffset = {origin.x, origin.y, BlockCount{0}};
+ copyInfo->bufferOffset = {}; // 0,0,0
+ copyInfo->copySize = {copySize.width, copySize.height, BlockCount{1}};
copyInfo->alignedOffset = offset;
- copyInfo->bufferSize = {copySize.width, copySize.height, TexelCount{1}};
+ copyInfo->bufferSize = {copySize.width, copySize.height, BlockCount{1}};
return copy;
}
@@ -626,21 +602,20 @@
uint64_t offset,
uint32_t bytesPerRow_in,
uint32_t rowsPerImage_in) {
- // TODO(424536624): Rework this function to compute in blocks, then convert to texels
- auto origin = TexelOrigin3D(origin_in);
- auto copySize = TexelExtent3D(copySize_in);
- auto blockInfo = TypedTexelBlockInfo(blockInfo_in);
- auto rowsPerImage = BlockCount(rowsPerImage_in);
- auto blocksPerRow = blockInfo.BytesToBlocks(bytesPerRow_in);
+ TypedTexelBlockInfo blockInfo{blockInfo_in};
+ BlockOrigin3D origin = blockInfo.ToBlock(origin_in);
+ BlockExtent3D copySize = blockInfo.ToBlock(copySize_in);
+ BlockCount rowsPerImage{rowsPerImage_in};
+ BlockCount blocksPerRow = blockInfo.BytesToBlocks(bytesPerRow_in);
TextureCopySubresource copy;
- Origin3D bufferOffset = {0, 0, 0};
+ BlockOrigin3D bufferOffset{BlockCount{0}, BlockCount{0}, BlockCount{0}};
// You can visualize the data in the buffer (bufferLocation) like the inline comments.
// * copy data is visualized as '+'.
- const TexelCount depthInCopy1 = copySize.depthOrArrayLayers - TexelCount{1};
- if (depthInCopy1 > TexelCount{0}) {
+ const BlockCount depthInCopy1 = copySize.depthOrArrayLayers - BlockCount{1};
+ if (depthInCopy1 > BlockCount{0}) {
// `bufferLocation` in the 1st copy (first `depthInCopy1` images, optional):
//
// bufferOffset(0, 0, 0)
@@ -666,8 +641,7 @@
copyInfo1->textureOffset = origin;
copyInfo1->copySize = {copySize.width, copySize.height, depthInCopy1};
copyInfo1->alignedOffset = offset;
- copyInfo1->bufferSize = {copySize.width, blockInfo.ToTexelHeight(rowsPerImage),
- depthInCopy1};
+ copyInfo1->bufferSize = {copySize.width, rowsPerImage, depthInCopy1};
}
{
@@ -689,16 +663,16 @@
// ^
// End of all buffer data
//
- DAWN_ASSERT(copySize.depthOrArrayLayers >= TexelCount{1});
- constexpr TexelCount depthInCopy2{1};
- const TexelCount rowsPerImageInTexels2 = copySize.height;
+ DAWN_ASSERT(copySize.depthOrArrayLayers >= BlockCount{1});
+ constexpr BlockCount depthInCopy2{1};
+ const BlockCount rowsPerImageInTexels2 = copySize.height;
auto* copyInfo2 = copy.AddCopy();
copyInfo2->bufferOffset = bufferOffset;
copyInfo2->textureOffset = {origin.x, origin.y, origin.z + depthInCopy1};
copyInfo2->copySize = {copySize.width, copySize.height, depthInCopy2};
- copyInfo2->alignedOffset = offset + blockInfo.ToBytes(blocksPerRow * rowsPerImage *
- blockInfo.ToBlockDepth(depthInCopy1));
+ copyInfo2->alignedOffset =
+ offset + blockInfo.ToBytes(blocksPerRow * rowsPerImage * depthInCopy1);
copyInfo2->bufferSize = {copySize.width, rowsPerImageInTexels2, depthInCopy2};
}
diff --git a/src/dawn/native/d3d12/TextureCopySplitter.h b/src/dawn/native/d3d12/TextureCopySplitter.h
index 4703377..3f7a020 100644
--- a/src/dawn/native/d3d12/TextureCopySplitter.h
+++ b/src/dawn/native/d3d12/TextureCopySplitter.h
@@ -49,13 +49,13 @@
// The 512-byte aligned offset into buffer
uint64_t alignedOffset = 0;
// Offset into texture
- TexelOrigin3D textureOffset;
+ BlockOrigin3D textureOffset;
// Offset into buffer
- TexelOrigin3D bufferOffset;
+ BlockOrigin3D bufferOffset;
// width,height,depth of the texture linearly laid out in the buffer
- TexelExtent3D bufferSize;
+ BlockExtent3D bufferSize;
// width,height,depth to copy
- TexelExtent3D copySize;
+ BlockExtent3D copySize;
};
CopyInfo* AddCopy();
diff --git a/src/dawn/native/d3d12/UtilsD3D12.cpp b/src/dawn/native/d3d12/UtilsD3D12.cpp
index a294975..7d828ee 100644
--- a/src/dawn/native/d3d12/UtilsD3D12.cpp
+++ b/src/dawn/native/d3d12/UtilsD3D12.cpp
@@ -105,7 +105,7 @@
D3D12_TEXTURE_COPY_LOCATION ComputeBufferLocationForCopyTextureRegion(
const Texture* texture,
ID3D12Resource* bufferResource,
- const Extent3D& bufferSize,
+ const TexelExtent3D& bufferSize,
const uint64_t offset,
const uint32_t rowPitch,
Aspect aspect) {
@@ -115,9 +115,10 @@
bufferLocation.PlacedFootprint.Offset = offset;
bufferLocation.PlacedFootprint.Footprint.Format =
texture->GetD3D12CopyableSubresourceFormat(aspect);
- bufferLocation.PlacedFootprint.Footprint.Width = bufferSize.width;
- bufferLocation.PlacedFootprint.Footprint.Height = bufferSize.height;
- bufferLocation.PlacedFootprint.Footprint.Depth = bufferSize.depthOrArrayLayers;
+ bufferLocation.PlacedFootprint.Footprint.Width = static_cast<uint32_t>(bufferSize.width);
+ bufferLocation.PlacedFootprint.Footprint.Height = static_cast<uint32_t>(bufferSize.height);
+ bufferLocation.PlacedFootprint.Footprint.Depth =
+ static_cast<uint32_t>(bufferSize.depthOrArrayLayers);
bufferLocation.PlacedFootprint.Footprint.RowPitch = rowPitch;
return bufferLocation;
}
@@ -192,37 +193,42 @@
ID3D12Resource* bufferResource,
uint64_t baseOffset,
uint64_t bufferBytesPerRow,
+ const TexelBlockInfo& blockInfo_in,
TextureBase* textureBase,
uint32_t textureMiplevel,
uint32_t textureLayer,
Aspect aspect) {
Texture* texture = ToBackend(textureBase);
+ TypedTexelBlockInfo blockInfo{blockInfo_in};
const D3D12_TEXTURE_COPY_LOCATION textureLocation =
ComputeTextureCopyLocationForTexture(texture, textureMiplevel, textureLayer, aspect);
for (uint32_t i = 0; i < baseCopySplit.count; ++i) {
const TextureCopySubresource::CopyInfo& info = baseCopySplit.copies[i];
+ TexelOrigin3D textureOffset = blockInfo.ToTexel(info.textureOffset);
+ TexelOrigin3D bufferOffset = blockInfo.ToTexel(info.bufferOffset);
+ TexelExtent3D copySize = blockInfo.ToTexel(info.copySize);
+ TexelExtent3D bufferSize = blockInfo.ToTexel(info.bufferSize);
+
const uint64_t offsetBytes = info.alignedOffset + baseOffset;
const D3D12_TEXTURE_COPY_LOCATION bufferLocation =
- ComputeBufferLocationForCopyTextureRegion(texture, bufferResource,
- info.bufferSize.ToExtent3D(), offsetBytes,
- bufferBytesPerRow, aspect);
+ ComputeBufferLocationForCopyTextureRegion(texture, bufferResource, bufferSize,
+ offsetBytes, bufferBytesPerRow, aspect);
if (direction == BufferTextureCopyDirection::B2T) {
- const D3D12_BOX sourceRegion = ComputeD3D12BoxFromOffsetAndSize(
- info.bufferOffset.ToOrigin3D(), info.copySize.ToExtent3D());
- const Origin3D textureOffset = info.textureOffset.ToOrigin3D();
- commandList->CopyTextureRegion(&textureLocation, textureOffset.x, textureOffset.y,
- textureOffset.z, &bufferLocation, &sourceRegion);
+ const D3D12_BOX sourceRegion =
+ ComputeD3D12BoxFromOffsetAndSize(bufferOffset.ToOrigin3D(), copySize.ToExtent3D());
+ const Origin3D to = textureOffset.ToOrigin3D();
+ commandList->CopyTextureRegion(&textureLocation, to.x, to.y, to.z, &bufferLocation,
+ &sourceRegion);
} else {
DAWN_ASSERT(direction == BufferTextureCopyDirection::T2B);
- const D3D12_BOX sourceRegion = ComputeD3D12BoxFromOffsetAndSize(
- info.textureOffset.ToOrigin3D(), info.copySize.ToExtent3D());
- const Origin3D bufferOffset = info.bufferOffset.ToOrigin3D();
-
- commandList->CopyTextureRegion(&bufferLocation, bufferOffset.x, bufferOffset.y,
- bufferOffset.z, &textureLocation, &sourceRegion);
+ const D3D12_BOX sourceRegion =
+ ComputeD3D12BoxFromOffsetAndSize(textureOffset.ToOrigin3D(), copySize.ToExtent3D());
+ const Origin3D bo = bufferOffset.ToOrigin3D();
+ commandList->CopyTextureRegion(&bufferLocation, bo.x, bo.y, bo.z, &textureLocation,
+ &sourceRegion);
}
}
}
@@ -260,10 +266,10 @@
const uint64_t bufferOffsetForNextLayer = bufferOffsetsForNextLayer[splitIndex];
const uint32_t copyTextureLayer = copyLayer + textureCopy.origin.z;
- RecordBufferTextureCopyFromSplits(direction, commandList, copySplitPerLayerBase,
- bufferResource, bufferOffsetForNextLayer, bytesPerRow,
- textureCopy.texture.Get(), textureCopy.mipLevel,
- copyTextureLayer, textureCopy.aspect);
+ RecordBufferTextureCopyFromSplits(
+ direction, commandList, copySplitPerLayerBase, bufferResource, bufferOffsetForNextLayer,
+ bytesPerRow, blockInfo, textureCopy.texture.Get(), textureCopy.mipLevel,
+ copyTextureLayer, textureCopy.aspect);
bufferOffsetsForNextLayer[splitIndex] += bytesPerLayer * copySplits.copySubresources.size();
}
@@ -287,7 +293,7 @@
for (uint32_t copyLayer = 0; copyLayer < copySize.depthOrArrayLayers; ++copyLayer) {
uint32_t copyTextureLayer = copyLayer + textureCopy.origin.z;
RecordBufferTextureCopyFromSplits(direction, commandList, copySubresource, bufferResource,
- bufferOffsetForNextLayer, bytesPerRow,
+ bufferOffsetForNextLayer, bytesPerRow, blockInfo,
textureCopy.texture.Get(), textureCopy.mipLevel,
copyTextureLayer, textureCopy.aspect);
bufferOffsetForNextLayer += bytesPerLayer;
@@ -327,8 +333,8 @@
blockInfo, offset, bytesPerRow);
}
RecordBufferTextureCopyFromSplits(direction, commandList, copyRegions, bufferResource,
- 0, bytesPerRow, texture, textureCopy.mipLevel, 0,
- textureCopy.aspect);
+ 0, bytesPerRow, blockInfo, texture,
+ textureCopy.mipLevel, 0, textureCopy.aspect);
break;
}
@@ -357,8 +363,8 @@
offset, bytesPerRow, rowsPerImage);
}
RecordBufferTextureCopyFromSplits(direction, commandList, copyRegions, bufferResource,
- 0, bytesPerRow, texture, textureCopy.mipLevel, 0,
- textureCopy.aspect);
+ 0, bytesPerRow, blockInfo, texture,
+ textureCopy.mipLevel, 0, textureCopy.aspect);
break;
}
}
diff --git a/src/dawn/tests/unittests/d3d12/CopySplitTests.cpp b/src/dawn/tests/unittests/d3d12/CopySplitTests.cpp
index 619158e..a972bb4 100644
--- a/src/dawn/tests/unittests/d3d12/CopySplitTests.cpp
+++ b/src/dawn/tests/unittests/d3d12/CopySplitTests.cpp
@@ -78,12 +78,12 @@
}
// TODO(425944899): Store TexelOrigin3D in TextureSpec
-TexelOrigin3D ToTOrigin3D(const TextureSpec& textureSpec) {
+TexelOrigin3D ToTexelOrigin3D(const TextureSpec& textureSpec) {
return TexelOrigin3D{textureSpec.x, textureSpec.y, textureSpec.z};
}
// TODO(425944899): Store TexelExtent3D in TextureSpec
-TexelExtent3D ToTExtent3D(const TextureSpec& textureSpec) {
+TexelExtent3D ToTexelExtent3D(const TextureSpec& textureSpec) {
return TexelExtent3D{textureSpec.width, textureSpec.height, textureSpec.depthOrArrayLayers};
}
@@ -95,9 +95,10 @@
TypedTexelBlockInfo blockInfo = ToTypedTexelBlockInfo(textureSpec);
for (uint32_t i = 0; i < copySplit.count; ++i) {
const auto& copy = copySplit.copies[i];
- const TexelExtent3D& copySize = copy.copySize;
- const TexelOrigin3D& bufferOffset = copy.bufferOffset;
- const TexelExtent3D& bufferSize = copy.bufferSize;
+ // TODO(425944899): Rework this function to work in blocks, not texels
+ const TexelExtent3D& copySize = blockInfo.ToTexel(copy.copySize);
+ const TexelOrigin3D& bufferOffset = blockInfo.ToTexel(copy.bufferOffset);
+ const TexelExtent3D& bufferSize = blockInfo.ToTexel(copy.bufferSize);
ASSERT_LE(bufferOffset.x + copySize.width, bufferSize.width);
ASSERT_LE(bufferOffset.y + copySize.height, bufferSize.height);
ASSERT_LE(bufferOffset.z + copySize.depthOrArrayLayers, bufferSize.depthOrArrayLayers);
@@ -170,19 +171,21 @@
}
// Check that no pair of copy regions intersect each other
-void ValidateDisjoint(const TextureCopySubresource& copySplit) {
+void ValidateDisjoint(const TextureSpec& textureSpec, const TextureCopySubresource& copySplit) {
+ TypedTexelBlockInfo blockInfo = ToTypedTexelBlockInfo(textureSpec);
for (uint32_t i = 0; i < copySplit.count; ++i) {
const auto& a = copySplit.copies[i];
- const TexelExtent3D& copySizeA = a.copySize;
- const TexelOrigin3D& textureOffsetA = a.textureOffset;
+ // TODO(425944899): Rework this function to work in blocks, not texels
+ const TexelExtent3D& copySizeA = blockInfo.ToTexel(a.copySize);
+ const TexelOrigin3D& textureOffsetA = blockInfo.ToTexel(a.textureOffset);
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.
- const TexelExtent3D& copySizeB = b.copySize;
- const TexelOrigin3D& textureOffsetB = b.textureOffset;
+ const TexelExtent3D& copySizeB = blockInfo.ToTexel(b.copySize);
+ const TexelOrigin3D& textureOffsetB = blockInfo.ToTexel(b.textureOffset);
bool overlapX =
InclusiveRangesOverlap(textureOffsetA.x, textureOffsetA.x + copySizeA.width - 1_tc,
textureOffsetB.x, textureOffsetB.x + copySizeB.width - 1_tc);
@@ -201,9 +204,11 @@
void ValidateTextureBounds(const TextureSpec& textureSpec,
const TextureCopySubresource& copySplit) {
ASSERT_GT(copySplit.count, 0u);
+ TypedTexelBlockInfo blockInfo = ToTypedTexelBlockInfo(textureSpec);
- const TexelExtent3D& copySize0 = copySplit.copies[0].copySize;
- const TexelOrigin3D& textureOffset0 = copySplit.copies[0].textureOffset;
+ // TODO(425944899): Rework this function to work in blocks, not texels
+ const TexelExtent3D& copySize0 = blockInfo.ToTexel(copySplit.copies[0].copySize);
+ const TexelOrigin3D& textureOffset0 = blockInfo.ToTexel(copySplit.copies[0].textureOffset);
TexelCount minX = textureOffset0.x;
TexelCount minY = textureOffset0.y;
TexelCount minZ = textureOffset0.z;
@@ -213,11 +218,11 @@
for (uint32_t i = 1; i < copySplit.count; ++i) {
const auto& copy = copySplit.copies[i];
- const TexelOrigin3D& textureOffset = copy.textureOffset;
+ const TexelOrigin3D& textureOffset = blockInfo.ToTexel(copy.textureOffset);
minX = std::min(minX, textureOffset.x);
minY = std::min(minY, textureOffset.y);
minZ = std::min(minZ, textureOffset.z);
- const TexelExtent3D& copySize = copy.copySize;
+ const TexelExtent3D& copySize = blockInfo.ToTexel(copy.copySize);
maxX = std::max(maxX, textureOffset.x + copySize.width);
maxY = std::max(maxY, textureOffset.y + copySize.height);
maxZ = std::max(maxZ, textureOffset.z + copySize.depthOrArrayLayers);
@@ -234,15 +239,18 @@
// Validate that the number of pixels copied is exactly equal to the number of pixels in the
// texture region
void ValidatePixelCount(const TextureSpec& textureSpec, const TextureCopySubresource& copySplit) {
- TexelCount count{0};
+ TypedTexelBlockInfo blockInfo = ToTypedTexelBlockInfo(textureSpec);
+ TexelCount totalCopiedTexels{0};
for (uint32_t i = 0; i < copySplit.count; ++i) {
const auto& copy = copySplit.copies[i];
- const TexelExtent3D& copySize = copy.copySize;
- TexelCount copiedPixels = copySize.width * copySize.height * copySize.depthOrArrayLayers;
- ASSERT_GT(copiedPixels, 0_tc);
- count += copiedPixels;
+ // TODO(425944899): Rework this function to work in blocks, not texels
+ const TexelExtent3D& copySize = blockInfo.ToTexel(copy.copySize);
+ TexelCount copiedTexels = copySize.width * copySize.height * copySize.depthOrArrayLayers;
+ ASSERT_GT(copiedTexels, 0_tc);
+ totalCopiedTexels += copiedTexels;
}
- ASSERT_EQ(count, textureSpec.width * textureSpec.height * textureSpec.depthOrArrayLayers);
+ ASSERT_EQ(totalCopiedTexels,
+ textureSpec.width * textureSpec.height * textureSpec.depthOrArrayLayers);
}
// Check that every buffer offset is at the correct pixel location
@@ -256,23 +264,22 @@
for (uint32_t i = 0; i < copySplit.count; ++i) {
const auto& copy = copySplit.copies[i];
- const TexelOrigin3D& bufferOffset = copy.bufferOffset;
- const TexelOrigin3D& textureOffset = copy.textureOffset;
+ const BlockOrigin3D& bufferOffset = copy.bufferOffset;
+ const BlockOrigin3D& textureOffset = copy.textureOffset;
// Note that for relaxed, the row pitch (bytesPerRow) is not required to be 256 bytes,
// but Dawn currently doesn't do anything about this.
BlockCount rowPitchInBlocks = blockInfo.BytesToBlocks(bufferSpec.bytesPerRow);
BlockCount slicePitchInBlocks = rowPitchInBlocks * bufferSpec.rowsPerImage;
- BlockCount absoluteOffsetInBlocks =
- blockInfo.BytesToBlocks(copy.alignedOffset) + blockInfo.ToBlockWidth(bufferOffset.x) +
- blockInfo.ToBlockHeight(bufferOffset.y) * rowPitchInBlocks;
+ BlockCount absoluteOffsetInBlocks = blockInfo.BytesToBlocks(copy.alignedOffset) +
+ bufferOffset.x + bufferOffset.y * rowPitchInBlocks;
// 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(bufferOffset.y, textureSpec.blockHeight);
+ ASSERT_LE(bufferOffset.y, BlockCount{1});
}
- ASSERT_EQ(bufferOffset.z, 0_tc);
+ ASSERT_EQ(bufferOffset.z, 0_bc);
ASSERT_GE(absoluteOffsetInBlocks, blockInfo.BytesToBlocks(bufferSpec.offset));
@@ -283,10 +290,9 @@
BlockCount yBlocks = (relativeOffsetInBlocks % slicePitchInBlocks) / rowPitchInBlocks;
BlockCount xBlocks = relativeOffsetInBlocks % rowPitchInBlocks;
- ASSERT_EQ(textureOffset.x - textureSpec.x, blockInfo.ToTexelWidth(xBlocks));
- ASSERT_EQ(textureOffset.y - textureSpec.y, blockInfo.ToTexelHeight(yBlocks));
- ASSERT_EQ(textureOffset.z - textureSpec.z, blockInfo.ToTexelDepth(z))
- << "textureOffset: " << textureOffset.z;
+ ASSERT_EQ(textureOffset.x - blockInfo.ToBlockWidth(textureSpec.x), xBlocks);
+ ASSERT_EQ(textureOffset.y - blockInfo.ToBlockHeight(textureSpec.y), yBlocks);
+ ASSERT_EQ(textureOffset.z - blockInfo.ToBlockDepth(textureSpec.z), z);
}
}
@@ -297,7 +303,7 @@
bool relaxed) {
ValidateFootprints(textureSpec, bufferSpec, copySplit, dimension);
ValidateOffset(copySplit, relaxed);
- ValidateDisjoint(copySplit);
+ ValidateDisjoint(textureSpec, copySplit);
ValidateTextureBounds(textureSpec, copySplit);
ValidatePixelCount(textureSpec, copySplit);
ValidateBufferOffset(textureSpec, bufferSpec, copySplit, dimension, relaxed);
@@ -765,14 +771,14 @@
}
if (relaxed) {
copySplit = Compute2DTextureCopySubresourceWithRelaxedRowPitchAndOffset(
- ToTOrigin3D(textureSpec).ToOrigin3D(),
- ToTExtent3D(textureSpec).ToExtent3D(),
+ ToTexelOrigin3D(textureSpec).ToOrigin3D(),
+ ToTexelExtent3D(textureSpec).ToExtent3D(),
ToTypedTexelBlockInfo(textureSpec).ToTexelBlockInfo(), bufferSpec.offset,
bufferSpec.bytesPerRow);
} else {
copySplit = Compute2DTextureCopySubresource(
- ToTOrigin3D(textureSpec).ToOrigin3D(),
- ToTExtent3D(textureSpec).ToExtent3D(),
+ ToTexelOrigin3D(textureSpec).ToOrigin3D(),
+ ToTexelExtent3D(textureSpec).ToExtent3D(),
ToTypedTexelBlockInfo(textureSpec).ToTexelBlockInfo(), bufferSpec.offset,
bufferSpec.bytesPerRow);
}
@@ -781,14 +787,14 @@
case wgpu::TextureDimension::e3D: {
if (relaxed) {
copySplit = Compute3DTextureCopySubresourceWithRelaxedRowPitchAndOffset(
- ToTOrigin3D(textureSpec).ToOrigin3D(),
- ToTExtent3D(textureSpec).ToExtent3D(),
+ ToTexelOrigin3D(textureSpec).ToOrigin3D(),
+ ToTexelExtent3D(textureSpec).ToExtent3D(),
ToTypedTexelBlockInfo(textureSpec).ToTexelBlockInfo(), bufferSpec.offset,
bufferSpec.bytesPerRow, static_cast<uint32_t>(bufferSpec.rowsPerImage));
} else {
copySplit = Compute3DTextureCopySplits(
- ToTOrigin3D(textureSpec).ToOrigin3D(),
- ToTExtent3D(textureSpec).ToExtent3D(),
+ ToTexelOrigin3D(textureSpec).ToOrigin3D(),
+ ToTexelExtent3D(textureSpec).ToExtent3D(),
ToTypedTexelBlockInfo(textureSpec).ToTexelBlockInfo(), bufferSpec.offset,
bufferSpec.bytesPerRow, static_cast<uint32_t>(bufferSpec.rowsPerImage));
}
@@ -856,6 +862,9 @@
TEST_P(CopySplitTest, TextureX) {
for (TextureSpec textureSpec : kBaseTextureSpecs) {
for (uint32_t val : kCheckValues) {
+ if (TexelCount{val} % textureSpec.blockWidth != 0_tc) {
+ continue;
+ }
textureSpec.x = TexelCount{val};
for (const BufferSpec& bufferSpec : BaseBufferSpecs(textureSpec)) {
DoTest(textureSpec, bufferSpec);
@@ -867,6 +876,9 @@
TEST_P(CopySplitTest, TextureY) {
for (TextureSpec textureSpec : kBaseTextureSpecs) {
for (uint32_t val : kCheckValues) {
+ if (TexelCount{val} % textureSpec.blockHeight != 0_tc) {
+ continue;
+ }
textureSpec.y = TexelCount{val};
for (const BufferSpec& bufferSpec : BaseBufferSpecs(textureSpec)) {
DoTest(textureSpec, bufferSpec);