Optimize B2T and T2B copies with multiple texture layers on D3D12

This patch optimizes the implementation of buffer-to-texture and
texture-to-buffer computations on D3D12 backends by computing
TextureCopySplits once for all the 2D texture array layers in the
copy instead of computing it once per layer. You can see the
comments in the function D3D12::ComputeTextureCopySplits() for more
details.

BUG=dawn:453
TEST=dawn_end2end_tests

Change-Id: I1b66d24d2418147957fbe03e2c25144bd043a62e
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/24643
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
This commit is contained in:
Jiawei Shao 2020-07-15 08:33:39 +00:00 committed by Commit Bot service account
parent b31f5e717e
commit 3b17f0bde8
6 changed files with 321 additions and 99 deletions

View File

@ -80,6 +80,67 @@ namespace dawn_native { namespace d3d12 {
copySize.depth == srcSize.depth;
}
void RecordCopyBufferToTextureFromTextureCopySplit(ID3D12GraphicsCommandList* commandList,
const Texture2DCopySplit& baseCopySplit,
Buffer* buffer,
uint64_t baseOffset,
uint64_t bufferBytesPerRow,
Texture* texture,
uint32_t textureMiplevel,
uint32_t textureSlice) {
const D3D12_TEXTURE_COPY_LOCATION textureLocation =
ComputeTextureCopyLocationForTexture(texture, textureMiplevel, textureSlice);
const uint64_t offset = baseCopySplit.offset + baseOffset;
for (uint32_t i = 0; i < baseCopySplit.count; ++i) {
const Texture2DCopySplit::CopyInfo& info = baseCopySplit.copies[i];
// TODO(jiawei.shao@intel.com): pre-compute bufferLocation and sourceRegion as
// members in Texture2DCopySplit::CopyInfo.
const D3D12_TEXTURE_COPY_LOCATION bufferLocation =
ComputeBufferLocationForCopyTextureRegion(texture, buffer->GetD3D12Resource(),
info.bufferSize, offset,
bufferBytesPerRow);
const D3D12_BOX sourceRegion =
ComputeD3D12BoxFromOffsetAndSize(info.bufferOffset, info.copySize);
commandList->CopyTextureRegion(&textureLocation, info.textureOffset.x,
info.textureOffset.y, info.textureOffset.z,
&bufferLocation, &sourceRegion);
}
}
void RecordCopyTextureToBufferFromTextureCopySplit(ID3D12GraphicsCommandList* commandList,
const Texture2DCopySplit& baseCopySplit,
Buffer* buffer,
uint64_t baseOffset,
uint64_t bufferBytesPerRow,
Texture* texture,
uint32_t textureMiplevel,
uint32_t textureSlice) {
const D3D12_TEXTURE_COPY_LOCATION textureLocation =
ComputeTextureCopyLocationForTexture(texture, textureMiplevel, textureSlice);
const uint64_t offset = baseCopySplit.offset + baseOffset;
for (uint32_t i = 0; i < baseCopySplit.count; ++i) {
const Texture2DCopySplit::CopyInfo& info = baseCopySplit.copies[i];
// TODO(jiawei.shao@intel.com): pre-compute bufferLocation and sourceRegion as
// members in Texture2DCopySplit::CopyInfo.
const D3D12_TEXTURE_COPY_LOCATION bufferLocation =
ComputeBufferLocationForCopyTextureRegion(texture, buffer->GetD3D12Resource(),
info.bufferSize, offset,
bufferBytesPerRow);
const D3D12_BOX sourceRegion =
ComputeD3D12BoxFromOffsetAndSize(info.textureOffset, info.copySize);
commandList->CopyTextureRegion(&bufferLocation, info.bufferOffset.x,
info.bufferOffset.y, info.bufferOffset.z,
&textureLocation, &sourceRegion);
}
}
} // anonymous namespace
class BindGroupStateTracker : public BindGroupAndStorageBarrierTrackerBase<false, uint64_t> {
@ -617,46 +678,42 @@ namespace dawn_native { namespace d3d12 {
texture->TrackUsageAndTransitionNow(commandContext, wgpu::TextureUsage::CopyDst,
subresources);
// See comments in ComputeTextureCopySplits() for more details.
const TextureCopySplits copySplits = ComputeTextureCopySplits(
copy->destination.origin, copy->copySize, texture->GetFormat(),
copy->source.offset, copy->source.bytesPerRow, copy->source.rowsPerImage);
const uint64_t bytesPerSlice =
copy->source.bytesPerRow *
(copy->source.rowsPerImage / texture->GetFormat().blockHeight);
const dawn_native::Extent3D copyOneLayerSize = {copy->copySize.width,
copy->copySize.height, 1};
uint64_t bufferOffsetForNextSlice = 0;
for (uint32_t copySlice = copy->destination.origin.z;
copySlice < copy->destination.origin.z + copy->copySize.depth;
++copySlice) {
// TODO(jiawei.shao@intel.com): compute copySplit once for all texture array
// layers when possible.
Origin3D destinationOriginInSubresource = copy->destination.origin;
destinationOriginInSubresource.z = 0;
auto copySplit = ComputeTextureCopySplit(
destinationOriginInSubresource, copyOneLayerSize, texture->GetFormat(),
bufferOffsetForNextSlice + copy->source.offset,
copy->source.bytesPerRow, copy->source.rowsPerImage);
// copySplits.copies2D[1] is always calculated for the second copy slice with
// extra "bytesPerSlice" copy offset compared with the first copy slice. So
// here we use an array bufferOffsetsForNextSlice to record the extra offsets
// for each copy slice: bufferOffsetsForNextSlice[0] is the extra offset for
// the next copy slice that uses copySplits.copies2D[0], and
// bufferOffsetsForNextSlice[1] is the extra offset for the next copy slice
// that uses copySplits.copies2D[1].
std::array<uint64_t, TextureCopySplits::kMaxTextureCopySplits>
bufferOffsetsForNextSlice = {{0u, 0u}};
for (uint32_t copySlice = 0; copySlice < copy->copySize.depth; ++copySlice) {
const uint32_t splitIndex = copySlice % copySplits.copies2D.size();
D3D12_TEXTURE_COPY_LOCATION textureLocation =
ComputeTextureCopyLocationForTexture(
texture, copy->destination.mipLevel, copySlice);
const Texture2DCopySplit& copySplitPerLayerBase =
copySplits.copies2D[splitIndex];
const uint64_t bufferOffsetForNextSlice =
bufferOffsetsForNextSlice[splitIndex];
const uint32_t copyTextureLayer = copySlice + copy->destination.origin.z;
for (uint32_t i = 0; i < copySplit.count; ++i) {
const TextureCopySplit::CopyInfo& info = copySplit.copies[i];
RecordCopyBufferToTextureFromTextureCopySplit(
commandList, copySplitPerLayerBase, buffer, bufferOffsetForNextSlice,
copy->source.bytesPerRow, texture, copy->destination.mipLevel,
copyTextureLayer);
D3D12_TEXTURE_COPY_LOCATION bufferLocation =
ComputeBufferLocationForCopyTextureRegion(
texture, buffer->GetD3D12Resource(), info.bufferSize,
copySplit.offset, copy->source.bytesPerRow);
D3D12_BOX sourceRegion =
ComputeD3D12BoxFromOffsetAndSize(info.bufferOffset, info.copySize);
commandList->CopyTextureRegion(
&textureLocation, info.textureOffset.x, info.textureOffset.y,
info.textureOffset.z, &bufferLocation, &sourceRegion);
bufferOffsetsForNextSlice[splitIndex] +=
bytesPerSlice * copySplits.copies2D.size();
}
bufferOffsetForNextSlice += bytesPerSlice;
}
break;
}
@ -674,46 +731,43 @@ namespace dawn_native { namespace d3d12 {
subresources);
buffer->TrackUsageAndTransitionNow(commandContext, wgpu::BufferUsage::CopyDst);
// See comments around ComputeTextureCopySplits() for more details.
const TextureCopySplits copySplits = ComputeTextureCopySplits(
copy->source.origin, copy->copySize, texture->GetFormat(),
copy->destination.offset, copy->destination.bytesPerRow,
copy->destination.rowsPerImage);
const uint64_t bytesPerSlice =
copy->destination.bytesPerRow *
(copy->destination.rowsPerImage / texture->GetFormat().blockHeight);
const dawn_native::Extent3D copyOneLayerSize = {copy->copySize.width,
copy->copySize.height, 1};
uint64_t bufferOffsetForNextSlice = 0;
for (uint32_t copySlice = copy->source.origin.z;
copySlice < copy->source.origin.z + copy->copySize.depth; ++copySlice) {
// TODO(jiawei.shao@intel.com): compute copySplit once for all texture array
// layers when possible.
Origin3D sourceOriginInSubresource = copy->source.origin;
sourceOriginInSubresource.z = 0;
TextureCopySplit copySplit = ComputeTextureCopySplit(
sourceOriginInSubresource, copyOneLayerSize, texture->GetFormat(),
bufferOffsetForNextSlice + copy->destination.offset,
copy->destination.bytesPerRow, copy->destination.rowsPerImage);
// copySplits.copies2D[1] is always calculated for the second copy slice with
// extra "bytesPerSlice" copy offset compared with the first copy slice. So
// here we use an array bufferOffsetsForNextSlice to record the extra offsets
// for each copy slice: bufferOffsetsForNextSlice[0] is the extra offset for
// the next copy slice that uses copySplits.copies2D[0], and
// bufferOffsetsForNextSlice[1] is the extra offset for the next copy slice
// that uses copySplits.copies2D[1].
std::array<uint64_t, TextureCopySplits::kMaxTextureCopySplits>
bufferOffsetsForNextSlice = {{0u, 0u}};
for (uint32_t copySlice = 0; copySlice < copy->copySize.depth; ++copySlice) {
const uint32_t splitIndex = copySlice % copySplits.copies2D.size();
D3D12_TEXTURE_COPY_LOCATION textureLocation =
ComputeTextureCopyLocationForTexture(texture, copy->source.mipLevel,
copySlice);
const Texture2DCopySplit& copySplitPerLayerBase =
copySplits.copies2D[splitIndex];
const uint64_t bufferOffsetForNextSlice =
bufferOffsetsForNextSlice[splitIndex];
const uint32_t copyTextureLayer = copySlice + copy->source.origin.z;
for (uint32_t i = 0; i < copySplit.count; ++i) {
const TextureCopySplit::CopyInfo& info = copySplit.copies[i];
RecordCopyTextureToBufferFromTextureCopySplit(
commandList, copySplitPerLayerBase, buffer, bufferOffsetForNextSlice,
copy->destination.bytesPerRow, texture, copy->source.mipLevel,
copyTextureLayer);
D3D12_TEXTURE_COPY_LOCATION bufferLocation =
ComputeBufferLocationForCopyTextureRegion(
texture, buffer->GetD3D12Resource(), info.bufferSize,
copySplit.offset, copy->destination.bytesPerRow);
D3D12_BOX sourceRegion =
ComputeD3D12BoxFromOffsetAndSize(info.textureOffset, info.copySize);
commandList->CopyTextureRegion(&bufferLocation, info.bufferOffset.x,
info.bufferOffset.y, info.bufferOffset.z,
&textureLocation, &sourceRegion);
bufferOffsetsForNextSlice[splitIndex] +=
bytesPerSlice * copySplits.copies2D.size();
}
bufferOffsetForNextSlice += bytesPerSlice;
}
break;
}

View File

@ -37,13 +37,13 @@ namespace dawn_native { namespace d3d12 {
}
} // namespace
TextureCopySplit ComputeTextureCopySplit(Origin3D origin,
Texture2DCopySplit ComputeTextureCopySplit(Origin3D origin,
Extent3D copySize,
const Format& format,
uint64_t offset,
uint32_t bytesPerRow,
uint32_t rowsPerImage) {
TextureCopySplit copy;
Texture2DCopySplit copy;
ASSERT(bytesPerRow % format.blockByteSize == 0);
@ -183,4 +183,50 @@ namespace dawn_native { namespace d3d12 {
return copy;
}
TextureCopySplits ComputeTextureCopySplits(Origin3D origin,
Extent3D copySize,
const Format& format,
uint64_t offset,
uint32_t bytesPerRow,
uint32_t rowsPerImage) {
TextureCopySplits copies;
const uint64_t bytesPerSlice = bytesPerRow * (rowsPerImage / format.blockHeight);
// The function ComputeTextureCopySplit() decides how to split the copy based on:
// - the alignment of the buffer offset with D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT (512)
// - the alignment of the buffer offset with D3D12_TEXTURE_DATA_PITCH_ALIGNMENT (256)
// Each slice of a 2D array or 3D copy might need to be split, but because of the WebGPU
// constraint that "bytesPerRow" must be a multiple of 256, all odd (resp. all even) slices
// will be at an offset multiple of 512 of each other, which means they will all result in
// the same 2D split. Thus we can just compute the copy splits for the first and second
// slices, and reuse them for the remaining slices by adding the related offset of each
// slice. Moreover, if "rowsPerImage" is even, both the first and second copy layers can
// share the same copy split, so in this situation we just need to compute copy split once
// and reuse it for all the slices.
const dawn_native::Extent3D copyOneLayerSize = {copySize.width, copySize.height, 1};
const dawn_native::Origin3D copyFirstLayerOrigin = {origin.x, origin.y, 0};
copies.copies2D[0] = ComputeTextureCopySplit(copyFirstLayerOrigin, copyOneLayerSize, format,
offset, bytesPerRow, rowsPerImage);
// When the copy only refers one texture 2D array layer copies.copies2D[1] will never be
// used so we can safely early return here.
if (copySize.depth == 1) {
return copies;
}
if (bytesPerSlice % D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT == 0) {
copies.copies2D[1] = copies.copies2D[0];
copies.copies2D[1].offset += bytesPerSlice;
} else {
const uint64_t bufferOffsetNextLayer = offset + bytesPerSlice;
copies.copies2D[1] =
ComputeTextureCopySplit(copyFirstLayerOrigin, copyOneLayerSize, format,
bufferOffsetNextLayer, bytesPerRow, rowsPerImage);
}
return copies;
}
}} // namespace dawn_native::d3d12

View File

@ -27,7 +27,7 @@ namespace dawn_native {
namespace dawn_native { namespace d3d12 {
struct TextureCopySplit {
struct Texture2DCopySplit {
static constexpr unsigned int kMaxTextureCopyRegions = 2;
struct CopyInfo {
@ -43,7 +43,20 @@ namespace dawn_native { namespace d3d12 {
std::array<CopyInfo, kMaxTextureCopyRegions> copies;
};
TextureCopySplit ComputeTextureCopySplit(Origin3D origin,
struct TextureCopySplits {
static constexpr uint32_t kMaxTextureCopySplits = 2;
std::array<Texture2DCopySplit, kMaxTextureCopySplits> copies2D;
};
Texture2DCopySplit ComputeTextureCopySplit(Origin3D origin,
Extent3D copySize,
const Format& format,
uint64_t offset,
uint32_t bytesPerRow,
uint32_t rowsPerImage);
TextureCopySplits ComputeTextureCopySplits(Origin3D origin,
Extent3D copySize,
const Format& format,
uint64_t offset,

View File

@ -926,7 +926,7 @@ namespace dawn_native { namespace d3d12 {
Extent3D copySize = GetMipLevelVirtualSize(level);
uint32_t rowsPerImage = GetHeight();
TextureCopySplit copySplit =
Texture2DCopySplit copySplit =
ComputeTextureCopySplit({0, 0, 0}, copySize, GetFormat(),
uploadHandle.startOffset, bytesPerRow, rowsPerImage);
@ -942,7 +942,7 @@ namespace dawn_native { namespace d3d12 {
D3D12_TEXTURE_COPY_LOCATION textureLocation =
ComputeTextureCopyLocationForTexture(this, level, layer);
for (uint32_t i = 0; i < copySplit.count; ++i) {
TextureCopySplit::CopyInfo& info = copySplit.copies[i];
Texture2DCopySplit::CopyInfo& info = copySplit.copies[i];
D3D12_TEXTURE_COPY_LOCATION bufferLocation =
ComputeBufferLocationForCopyTextureRegion(

View File

@ -746,6 +746,60 @@ TEST_P(CopyTests_T2B, Texture2DArrayRegionNonzeroRowsPerImage) {
DoTest(textureSpec, bufferSpec, {kWidth, kHeight, kCopyLayers});
}
// Test a special code path in the D3D12 backends when (BytesPerRow * RowsPerImage) is not a
// multiple of 512.
TEST_P(CopyTests_T2B, Texture2DArrayRegionWithOffsetOddRowsPerImage) {
// TODO(jiawei.shao@intel.com): investigate why copies with multiple texture array layers fail
// with swiftshader.
DAWN_SKIP_TEST_IF(IsSwiftshader());
constexpr uint32_t kWidth = 64;
constexpr uint32_t kHeight = 128;
constexpr uint32_t kLayers = 8u;
constexpr uint32_t kBaseLayer = 2u;
constexpr uint32_t kCopyLayers = 5u;
constexpr uint32_t kRowsPerImage = kHeight + 1;
TextureSpec textureSpec;
textureSpec.copyOrigin = {0, 0, kBaseLayer};
textureSpec.textureSize = {kWidth, kHeight, kLayers};
textureSpec.level = 0;
BufferSpec bufferSpec = MinimumBufferSpec(kWidth, kRowsPerImage, kCopyLayers, false);
bufferSpec.offset += 128u;
bufferSpec.size += 128u;
bufferSpec.rowsPerImage = kRowsPerImage;
DoTest(textureSpec, bufferSpec, {kWidth, kHeight, kCopyLayers});
}
// Test a special code path in the D3D12 backends when (BytesPerRow * RowsPerImage) is a multiple
// of 512.
TEST_P(CopyTests_T2B, Texture2DArrayRegionWithOffsetEvenRowsPerImage) {
// TODO(jiawei.shao@intel.com): investigate why copies with multiple texture array layers fail
// with swiftshader.
DAWN_SKIP_TEST_IF(IsSwiftshader());
constexpr uint32_t kWidth = 64;
constexpr uint32_t kHeight = 128;
constexpr uint32_t kLayers = 8u;
constexpr uint32_t kBaseLayer = 2u;
constexpr uint32_t kCopyLayers = 4u;
constexpr uint32_t kRowsPerImage = kHeight + 2;
TextureSpec textureSpec;
textureSpec.copyOrigin = {0, 0, kBaseLayer};
textureSpec.textureSize = {kWidth, kHeight, kLayers};
textureSpec.level = 0;
BufferSpec bufferSpec = MinimumBufferSpec(kWidth, kRowsPerImage, kCopyLayers, false);
bufferSpec.offset += 128u;
bufferSpec.size += 128u;
bufferSpec.rowsPerImage = kRowsPerImage;
DoTest(textureSpec, bufferSpec, {kWidth, kHeight, kCopyLayers});
}
DAWN_INSTANTIATE_TEST(CopyTests_T2B,
D3D12Backend(),
MetalBackend(),
@ -1094,6 +1148,60 @@ TEST_P(CopyTests_B2T, Texture2DArrayRegionNonzeroRowsPerImage) {
DoTest(textureSpec, bufferSpec, {kWidth, kHeight, kCopyLayers});
}
// Test a special code path in the D3D12 backends when (BytesPerRow * RowsPerImage) is not a
// multiple of 512.
TEST_P(CopyTests_B2T, Texture2DArrayRegionWithOffsetOddRowsPerImage) {
// TODO(jiawei.shao@intel.com): investigate why copies with multiple texture array layers fail
// with swiftshader.
DAWN_SKIP_TEST_IF(IsSwiftshader());
constexpr uint32_t kWidth = 64;
constexpr uint32_t kHeight = 128;
constexpr uint32_t kLayers = 8u;
constexpr uint32_t kBaseLayer = 2u;
constexpr uint32_t kCopyLayers = 5u;
constexpr uint32_t kRowsPerImage = kHeight + 1;
TextureSpec textureSpec;
textureSpec.copyOrigin = {0, 0, kBaseLayer};
textureSpec.textureSize = {kWidth, kHeight, kLayers};
textureSpec.level = 0;
BufferSpec bufferSpec = MinimumBufferSpec(kWidth, kRowsPerImage, kCopyLayers, false);
bufferSpec.offset += 128u;
bufferSpec.size += 128u;
bufferSpec.rowsPerImage = kRowsPerImage;
DoTest(textureSpec, bufferSpec, {kWidth, kHeight, kCopyLayers});
}
// Test a special code path in the D3D12 backends when (BytesPerRow * RowsPerImage) is a multiple
// of 512.
TEST_P(CopyTests_B2T, Texture2DArrayRegionWithOffsetEvenRowsPerImage) {
// TODO(jiawei.shao@intel.com): investigate why copies with multiple texture array layers fail
// with swiftshader.
DAWN_SKIP_TEST_IF(IsSwiftshader());
constexpr uint32_t kWidth = 64;
constexpr uint32_t kHeight = 128;
constexpr uint32_t kLayers = 8u;
constexpr uint32_t kBaseLayer = 2u;
constexpr uint32_t kCopyLayers = 5u;
constexpr uint32_t kRowsPerImage = kHeight + 2;
TextureSpec textureSpec;
textureSpec.copyOrigin = {0, 0, kBaseLayer};
textureSpec.textureSize = {kWidth, kHeight, kLayers};
textureSpec.level = 0;
BufferSpec bufferSpec = MinimumBufferSpec(kWidth, kRowsPerImage, kCopyLayers, false);
bufferSpec.offset += 128u;
bufferSpec.size += 128u;
bufferSpec.rowsPerImage = kRowsPerImage;
DoTest(textureSpec, bufferSpec, {kWidth, kHeight, kCopyLayers});
}
DAWN_INSTANTIATE_TEST(CopyTests_B2T,
D3D12Backend(),
MetalBackend(),

View File

@ -44,7 +44,7 @@ namespace {
};
// Check that each copy region fits inside the buffer footprint
void ValidateFootprints(const TextureCopySplit& copySplit) {
void ValidateFootprints(const Texture2DCopySplit& copySplit) {
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);
@ -54,7 +54,7 @@ namespace {
}
// Check that the offset is aligned
void ValidateOffset(const TextureCopySplit& copySplit) {
void ValidateOffset(const Texture2DCopySplit& copySplit) {
ASSERT_TRUE(Align(copySplit.offset, D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT) ==
copySplit.offset);
}
@ -64,7 +64,7 @@ namespace {
}
// Check that no pair of copy regions intersect each other
void ValidateDisjoint(const TextureCopySplit& copySplit) {
void ValidateDisjoint(const Texture2DCopySplit& copySplit) {
for (uint32_t i = 0; i < copySplit.count; ++i) {
const auto& a = copySplit.copies[i];
for (uint32_t j = i + 1; j < copySplit.count; ++j) {
@ -84,7 +84,8 @@ namespace {
}
// Check that the union of the copy regions exactly covers the texture region
void ValidateTextureBounds(const TextureSpec& textureSpec, const TextureCopySplit& copySplit) {
void ValidateTextureBounds(const TextureSpec& textureSpec,
const Texture2DCopySplit& copySplit) {
ASSERT_TRUE(copySplit.count > 0);
uint32_t minX = copySplit.copies[0].textureOffset.x;
@ -114,7 +115,7 @@ namespace {
// 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 TextureCopySplit& copySplit) {
void ValidatePixelCount(const TextureSpec& textureSpec, const Texture2DCopySplit& copySplit) {
uint32_t count = 0;
for (uint32_t i = 0; i < copySplit.count; ++i) {
const auto& copy = copySplit.copies[i];
@ -126,7 +127,7 @@ namespace {
// Check that every buffer offset is at the correct pixel location
void ValidateBufferOffset(const TextureSpec& textureSpec,
const BufferSpec& bufferSpec,
const TextureCopySplit& copySplit) {
const Texture2DCopySplit& copySplit) {
ASSERT_TRUE(copySplit.count > 0);
uint32_t texelsPerBlock = textureSpec.blockWidth * textureSpec.blockHeight;
@ -161,7 +162,7 @@ namespace {
void ValidateCopySplit(const TextureSpec& textureSpec,
const BufferSpec& bufferSpec,
const TextureCopySplit& copySplit) {
const Texture2DCopySplit& copySplit) {
ValidateFootprints(copySplit);
ValidateOffset(copySplit);
ValidateDisjoint(copySplit);
@ -184,7 +185,7 @@ namespace {
return os;
}
std::ostream& operator<<(std::ostream& os, const TextureCopySplit& copySplit) {
std::ostream& operator<<(std::ostream& os, const Texture2DCopySplit& copySplit) {
os << "CopySplit" << std::endl;
for (uint32_t i = 0; i < copySplit.count; ++i) {
const auto& copy = copySplit.copies[i];
@ -286,14 +287,14 @@ namespace {
class CopySplitTest : public testing::Test {
protected:
TextureCopySplit DoTest(const TextureSpec& textureSpec, const BufferSpec& bufferSpec) {
Texture2DCopySplit DoTest(const TextureSpec& textureSpec, const BufferSpec& bufferSpec) {
ASSERT(textureSpec.width % textureSpec.blockWidth == 0 &&
textureSpec.height % textureSpec.blockHeight == 0);
dawn_native::Format fakeFormat = {};
fakeFormat.blockWidth = textureSpec.blockWidth;
fakeFormat.blockHeight = textureSpec.blockHeight;
fakeFormat.blockByteSize = textureSpec.texelBlockSizeInBytes;
TextureCopySplit copySplit = ComputeTextureCopySplit(
Texture2DCopySplit copySplit = ComputeTextureCopySplit(
{textureSpec.x, textureSpec.y, textureSpec.z},
{textureSpec.width, textureSpec.height, textureSpec.depth}, fakeFormat,
bufferSpec.offset, bufferSpec.bytesPerRow, bufferSpec.rowsPerImage);
@ -305,7 +306,7 @@ class CopySplitTest : public testing::Test {
TEST_F(CopySplitTest, General) {
for (TextureSpec textureSpec : kBaseTextureSpecs) {
for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) {
TextureCopySplit copySplit = DoTest(textureSpec, bufferSpec);
Texture2DCopySplit copySplit = DoTest(textureSpec, bufferSpec);
if (HasFatalFailure()) {
std::ostringstream message;
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec
@ -325,7 +326,7 @@ TEST_F(CopySplitTest, TextureWidth) {
}
textureSpec.width = val;
for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) {
TextureCopySplit copySplit = DoTest(textureSpec, bufferSpec);
Texture2DCopySplit copySplit = DoTest(textureSpec, bufferSpec);
if (HasFatalFailure()) {
std::ostringstream message;
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec
@ -346,7 +347,7 @@ TEST_F(CopySplitTest, TextureHeight) {
}
textureSpec.height = val;
for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) {
TextureCopySplit copySplit = DoTest(textureSpec, bufferSpec);
Texture2DCopySplit copySplit = DoTest(textureSpec, bufferSpec);
if (HasFatalFailure()) {
std::ostringstream message;
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec
@ -364,7 +365,7 @@ TEST_F(CopySplitTest, TextureX) {
for (uint32_t val : kCheckValues) {
textureSpec.x = val;
for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) {
TextureCopySplit copySplit = DoTest(textureSpec, bufferSpec);
Texture2DCopySplit copySplit = DoTest(textureSpec, bufferSpec);
if (HasFatalFailure()) {
std::ostringstream message;
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec
@ -382,7 +383,7 @@ TEST_F(CopySplitTest, TextureY) {
for (uint32_t val : kCheckValues) {
textureSpec.y = val;
for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) {
TextureCopySplit copySplit = DoTest(textureSpec, bufferSpec);
Texture2DCopySplit copySplit = DoTest(textureSpec, bufferSpec);
if (HasFatalFailure()) {
std::ostringstream message;
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec
@ -400,7 +401,7 @@ TEST_F(CopySplitTest, TexelSize) {
for (uint32_t texelSize : {4, 8, 16, 32, 64}) {
textureSpec.texelBlockSizeInBytes = texelSize;
for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) {
TextureCopySplit copySplit = DoTest(textureSpec, bufferSpec);
Texture2DCopySplit copySplit = DoTest(textureSpec, bufferSpec);
if (HasFatalFailure()) {
std::ostringstream message;
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec
@ -419,7 +420,7 @@ TEST_F(CopySplitTest, BufferOffset) {
for (uint32_t val : kCheckValues) {
bufferSpec.offset = textureSpec.texelBlockSizeInBytes * val;
TextureCopySplit copySplit = DoTest(textureSpec, bufferSpec);
Texture2DCopySplit copySplit = DoTest(textureSpec, bufferSpec);
if (HasFatalFailure()) {
std::ostringstream message;
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec
@ -439,7 +440,7 @@ TEST_F(CopySplitTest, RowPitch) {
for (uint32_t i = 0; i < 5; ++i) {
bufferSpec.bytesPerRow = baseRowPitch + i * 256;
TextureCopySplit copySplit = DoTest(textureSpec, bufferSpec);
Texture2DCopySplit copySplit = DoTest(textureSpec, bufferSpec);
if (HasFatalFailure()) {
std::ostringstream message;
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec
@ -459,7 +460,7 @@ TEST_F(CopySplitTest, ImageHeight) {
for (uint32_t i = 0; i < 5; ++i) {
bufferSpec.rowsPerImage = baseImageHeight + i * 256;
TextureCopySplit copySplit = DoTest(textureSpec, bufferSpec);
Texture2DCopySplit copySplit = DoTest(textureSpec, bufferSpec);
if (HasFatalFailure()) {
std::ostringstream message;
message << "Failed generating splits: " << textureSpec << ", " << bufferSpec