diff --git a/src/dawn_native/d3d12/CommandBufferD3D12.cpp b/src/dawn_native/d3d12/CommandBufferD3D12.cpp index 862aa46728..0a6261077d 100644 --- a/src/dawn_native/d3d12/CommandBufferD3D12.cpp +++ b/src/dawn_native/d3d12/CommandBufferD3D12.cpp @@ -521,9 +521,8 @@ namespace dawn_native { namespace d3d12 { texture->TransitionUsageNow(commandList, dawn::TextureUsageBit::TransferDst); auto copySplit = ComputeTextureCopySplit( - copy->destination.origin, copy->copySize, - texture->GetFormat().blockByteSize, copy->source.offset, - copy->source.rowPitch, copy->source.imageHeight); + copy->destination.origin, copy->copySize, texture->GetFormat(), + copy->source.offset, copy->source.rowPitch, copy->source.imageHeight); D3D12_TEXTURE_COPY_LOCATION textureLocation = CreateTextureCopyLocationForTexture(*texture, copy->destination.level, @@ -568,7 +567,7 @@ namespace dawn_native { namespace d3d12 { buffer->TransitionUsageNow(commandList, dawn::BufferUsageBit::TransferDst); auto copySplit = ComputeTextureCopySplit( - copy->source.origin, copy->copySize, texture->GetFormat().blockByteSize, + copy->source.origin, copy->copySize, texture->GetFormat(), copy->destination.offset, copy->destination.rowPitch, copy->destination.imageHeight); diff --git a/src/dawn_native/d3d12/TextureCopySplitter.cpp b/src/dawn_native/d3d12/TextureCopySplitter.cpp index 201c4634b0..aa76517912 100644 --- a/src/dawn_native/d3d12/TextureCopySplitter.cpp +++ b/src/dawn_native/d3d12/TextureCopySplitter.cpp @@ -20,31 +20,29 @@ namespace dawn_native { namespace d3d12 { namespace { - void ComputeTexelOffsets(uint32_t offset, - uint32_t rowPitch, - uint32_t slicePitch, - uint32_t texelSize, - Origin3D* texelOffset) { + Origin3D ComputeTexelOffsets(Format format, + uint32_t offset, + uint32_t rowPitch, + uint32_t slicePitch) { uint32_t byteOffsetX = offset % rowPitch; offset -= byteOffsetX; uint32_t byteOffsetY = offset % slicePitch; uint32_t byteOffsetZ = offset - byteOffsetY; - texelOffset->x = byteOffsetX / texelSize; - texelOffset->y = byteOffsetY / rowPitch; - texelOffset->z = byteOffsetZ / slicePitch; + return {byteOffsetX / format.blockByteSize * format.blockWidth, + byteOffsetY / rowPitch * format.blockHeight, byteOffsetZ / slicePitch}; } } // namespace TextureCopySplit ComputeTextureCopySplit(Origin3D origin, Extent3D copySize, - uint32_t texelSize, + Format format, uint64_t offset, uint32_t rowPitch, uint32_t imageHeight) { TextureCopySplit copy; - ASSERT(rowPitch % texelSize == 0); + ASSERT(rowPitch % format.blockByteSize == 0); uint64_t alignedOffset = offset & ~static_cast(D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT - 1); @@ -70,13 +68,13 @@ namespace dawn_native { namespace d3d12 { ASSERT(alignedOffset < offset); ASSERT(offset - alignedOffset < D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT); - Origin3D texelOffset; - ComputeTexelOffsets(static_cast(offset - alignedOffset), rowPitch, - rowPitch * imageHeight, texelSize, &texelOffset); + uint32_t slicePitch = rowPitch * (imageHeight / format.blockHeight); + Origin3D texelOffset = ComputeTexelOffsets( + format, static_cast(offset - alignedOffset), rowPitch, slicePitch); - uint32_t rowPitchInTexels = rowPitch / texelSize; - - if (copySize.width + texelOffset.x <= rowPitchInTexels) { + uint32_t copyBytesPerRowPitch = copySize.width / format.blockWidth * format.blockByteSize; + uint32_t byteOffsetInRowPitch = texelOffset.x / format.blockWidth * format.blockByteSize; + if (copyBytesPerRowPitch + byteOffsetInRowPitch <= rowPitch) { // The region's rows fit inside the row pitch. In this case, extend the width of the // PlacedFootprint and copy the buffer with an offset location // |<--------------- row pitch --------------->| @@ -152,13 +150,14 @@ namespace dawn_native { namespace d3d12 { copy.copies[0].textureOffset = origin; - ASSERT(rowPitchInTexels > texelOffset.x); - copy.copies[0].copySize.width = rowPitchInTexels - texelOffset.x; + ASSERT(rowPitch > byteOffsetInRowPitch); + uint32_t texelsPerRow = rowPitch / format.blockByteSize * format.blockWidth; + copy.copies[0].copySize.width = texelsPerRow - texelOffset.x; copy.copies[0].copySize.height = copySize.height; copy.copies[0].copySize.depth = copySize.depth; copy.copies[0].bufferOffset = texelOffset; - copy.copies[0].bufferSize.width = rowPitchInTexels; + copy.copies[0].bufferSize.width = texelsPerRow; copy.copies[0].bufferSize.height = imageHeight + texelOffset.y; copy.copies[0].bufferSize.depth = copySize.depth + texelOffset.z; @@ -172,10 +171,10 @@ namespace dawn_native { namespace d3d12 { copy.copies[1].copySize.depth = copySize.depth; copy.copies[1].bufferOffset.x = 0; - copy.copies[1].bufferOffset.y = texelOffset.y + 1; + copy.copies[1].bufferOffset.y = texelOffset.y + format.blockHeight; copy.copies[1].bufferOffset.z = texelOffset.z; copy.copies[1].bufferSize.width = copy.copies[1].copySize.width; - copy.copies[1].bufferSize.height = imageHeight + texelOffset.y + 1; + copy.copies[1].bufferSize.height = imageHeight + texelOffset.y + format.blockHeight; copy.copies[1].bufferSize.depth = copySize.depth + texelOffset.z; return copy; diff --git a/src/dawn_native/d3d12/TextureCopySplitter.h b/src/dawn_native/d3d12/TextureCopySplitter.h index e70a0e1576..540702f9ca 100644 --- a/src/dawn_native/d3d12/TextureCopySplitter.h +++ b/src/dawn_native/d3d12/TextureCopySplitter.h @@ -15,6 +15,7 @@ #ifndef DAWNNATIVE_D3D12_TEXTURECOPYSPLITTER_H_ #define DAWNNATIVE_D3D12_TEXTURECOPYSPLITTER_H_ +#include "dawn_native/Texture.h" #include "dawn_native/dawn_platform.h" #include @@ -39,7 +40,7 @@ namespace dawn_native { namespace d3d12 { TextureCopySplit ComputeTextureCopySplit(Origin3D origin, Extent3D copySize, - uint32_t texelSize, + Format format, uint64_t offset, uint32_t rowPitch, uint32_t imageHeight); diff --git a/src/dawn_native/d3d12/TextureD3D12.cpp b/src/dawn_native/d3d12/TextureD3D12.cpp index c428238754..da03dba6d6 100644 --- a/src/dawn_native/d3d12/TextureD3D12.cpp +++ b/src/dawn_native/d3d12/TextureD3D12.cpp @@ -64,20 +64,19 @@ namespace dawn_native { namespace d3d12 { // A multisampled resource must have either D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET or // D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL set in D3D12_RESOURCE_DESC::Flags. - // https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ns-d3d12-d3d12_resource - // _desc - if ((usage & dawn::TextureUsageBit::OutputAttachment) || isMultisampledTexture) { + // https://docs.microsoft.com/en-us/windows/desktop/api/d3d12/ns-d3d12-d3d12_resource_desc + // Currently all textures are zero-initialized via the render-target path so always add + // the render target flag, except for compressed textures for which the render-target + // flag is invalid. + // TODO(natlee@microsoft.com, jiawei.shao@intel.com): do not require render target for + // lazy clearing. + if ((usage & dawn::TextureUsageBit::OutputAttachment) || isMultisampledTexture || + !format.isCompressed) { if (format.HasDepthOrStencil()) { flags |= D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL; } else { flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; } - } else if ((usage & dawn::TextureUsageBit::TransferDst) || - (usage & dawn::TextureUsageBit::TransferSrc)) { - // if texture is used as copy source or destination, it may need to be - // cleared/initialized, which requires it to be a render target - // TODO(natlee@microsoft.com): optimize texture clearing without render target - flags |= D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET; } ASSERT(!(flags & D3D12_RESOURCE_FLAG_ALLOW_DEPTH_STENCIL) || @@ -114,6 +113,13 @@ namespace dawn_native { namespace d3d12 { return DXGI_FORMAT_B8G8R8A8_UNORM; case dawn::TextureFormat::Depth24PlusStencil8: return DXGI_FORMAT_D32_FLOAT_S8X24_UINT; + + // TODO(jiawei.shao@intel.com): support all BC formats + case dawn::TextureFormat::BC5RGSnorm: + return DXGI_FORMAT_BC5_SNORM; + case dawn::TextureFormat::BC5RGUnorm: + return DXGI_FORMAT_BC5_UNORM; + default: UNREACHABLE(); } @@ -335,6 +341,13 @@ namespace dawn_native { namespace d3d12 { uint32_t levelCount, uint32_t baseArrayLayer, uint32_t layerCount) { + // TODO(jiawei.shao@intel.com): initialize the textures in compressed formats with copies. + if (GetFormat().isCompressed) { + SetIsSubresourceContentInitialized(baseMipLevel, levelCount, baseArrayLayer, + layerCount); + return; + } + Device* device = ToBackend(GetDevice()); DescriptorHeapAllocator* descriptorHeapAllocator = device->GetDescriptorHeapAllocator(); diff --git a/src/tests/end2end/CompressedTextureFormatTests.cpp b/src/tests/end2end/CompressedTextureFormatTests.cpp index 91de5cbb44..3915a5c6cf 100644 --- a/src/tests/end2end/CompressedTextureFormatTests.cpp +++ b/src/tests/end2end/CompressedTextureFormatTests.cpp @@ -83,7 +83,8 @@ class CompressedTextureBCFormatTest : public DawnTest { bufferRowPitchInBytes = copyWidthInBlockAtLevel * CompressedFormatBlockSizeInBytes(copyConfig.format); } - uint32_t uploadBufferSize = bufferRowPitchInBytes * copyHeightInBlockAtLevel; + uint32_t uploadBufferSize = + copyConfig.bufferOffset + bufferRowPitchInBytes * copyHeightInBlockAtLevel; // Fill uploadData with the pre-prepared one-block compressed texture data. std::vector uploadData(uploadBufferSize, 0); @@ -546,5 +547,107 @@ TEST_P(CompressedTextureBCFormatTest, CopyPartofTextureSubResourceIntoNonZeroMip } } -// TODO(jiawei.shao@intel.com): support BC formats on D3D12, Metal and OpenGL backend -DAWN_INSTANTIATE_TEST(CompressedTextureBCFormatTest, VulkanBackend); +// Test the special case of the B2T copies on the D3D12 backend that the buffer offset and texture +// extent exactly fit the RowPitch. +TEST_P(CompressedTextureBCFormatTest, BufferOffsetAndExtentFitRowPitch) { + CopyConfig config; + config.textureWidthLevel0 = 8; + config.textureHeightLevel0 = 8; + config.rowPitchAlignment = kTextureRowPitchAlignment; + config.copyExtent3D = {config.textureWidthLevel0, config.textureHeightLevel0, 1}; + + const uint32_t blockCountPerRow = config.textureWidthLevel0 / kBCBlockWidthInTexels; + + for (dawn::TextureFormat format : kBCFormats) { + config.format = format; + + const uint32_t blockSizeInBytes = CompressedFormatBlockSizeInBytes(format); + const uint32_t blockCountPerRowPitch = config.rowPitchAlignment / blockSizeInBytes; + + config.bufferOffset = (blockCountPerRowPitch - blockCountPerRow) * blockSizeInBytes; + + TestCopyRegionIntoBCFormatTextures(config); + } +} + +// Test the special case of the B2T copies on the D3D12 backend that the buffer offset exceeds the +// slice pitch (slicePitch = rowPitch * (imageHeightInTexels / blockHeightInTexels)). On D3D12 +// backend the texelOffset.y will be greater than 0 after calcuting the texelOffset in the function +// ComputeTexelOffsets(). +TEST_P(CompressedTextureBCFormatTest, BufferOffsetExceedsSlicePitch) { + CopyConfig config; + config.textureWidthLevel0 = 8; + config.textureHeightLevel0 = 8; + config.rowPitchAlignment = kTextureRowPitchAlignment; + config.copyExtent3D = {config.textureWidthLevel0, config.textureHeightLevel0, 1}; + + const uint32_t blockCountPerRow = config.textureWidthLevel0 / kBCBlockWidthInTexels; + const uint32_t slicePitchInBytes = + config.rowPitchAlignment * (config.textureHeightLevel0 / kBCBlockHeightInTexels); + + for (dawn::TextureFormat format : kBCFormats) { + config.format = format; + + const uint32_t blockSizeInBytes = CompressedFormatBlockSizeInBytes(format); + const uint32_t blockCountPerRowPitch = config.rowPitchAlignment / blockSizeInBytes; + + config.bufferOffset = (blockCountPerRowPitch - blockCountPerRow) * blockSizeInBytes + + config.rowPitchAlignment + slicePitchInBytes; + + TestCopyRegionIntoBCFormatTextures(config); + } +} + +// Test the special case of the B2T copies on the D3D12 backend that the buffer offset and texture +// extent exceed the RowPitch. On D3D12 backend two copies are required for this case. +TEST_P(CompressedTextureBCFormatTest, CopyWithBufferOffsetAndExtentExceedRowPitch) { + CopyConfig config; + config.textureWidthLevel0 = 8; + config.textureHeightLevel0 = 8; + config.rowPitchAlignment = kTextureRowPitchAlignment; + config.copyExtent3D = {config.textureWidthLevel0, config.textureHeightLevel0, 1}; + + const uint32_t blockCountPerRow = config.textureWidthLevel0 / kBCBlockWidthInTexels; + + constexpr uint32_t kExceedRowBlockCount = 1; + + for (dawn::TextureFormat format : kBCFormats) { + config.format = format; + + const uint32_t blockSizeInBytes = CompressedFormatBlockSizeInBytes(format); + const uint32_t blockCountPerRowPitch = config.rowPitchAlignment / blockSizeInBytes; + config.bufferOffset = + (blockCountPerRowPitch - blockCountPerRow + kExceedRowBlockCount) * blockSizeInBytes; + + TestCopyRegionIntoBCFormatTextures(config); + } +} + +// Test the special case of the B2T copies on the D3D12 backend that the slicePitch is equal to the +// rowPitch. On D3D12 backend the texelOffset.z will be greater than 0 after calcuting the +// texelOffset in the function ComputeTexelOffsets(). +TEST_P(CompressedTextureBCFormatTest, RowPitchEqualToSlicePitch) { + CopyConfig config; + config.textureWidthLevel0 = 8; + config.textureHeightLevel0 = kBCBlockHeightInTexels; + config.rowPitchAlignment = kTextureRowPitchAlignment; + config.copyExtent3D = {config.textureWidthLevel0, config.textureHeightLevel0, 1}; + + const uint32_t blockCountPerRow = config.textureWidthLevel0 / kBCBlockWidthInTexels; + const uint32_t slicePitchInBytes = config.rowPitchAlignment; + + for (dawn::TextureFormat format : kBCFormats) { + config.format = format; + + const uint32_t blockSizeInBytes = CompressedFormatBlockSizeInBytes(format); + const uint32_t blockCountPerRowPitch = config.rowPitchAlignment / blockSizeInBytes; + + config.bufferOffset = + (blockCountPerRowPitch - blockCountPerRow) * blockSizeInBytes + slicePitchInBytes; + + TestCopyRegionIntoBCFormatTextures(config); + } +} + +// TODO(jiawei.shao@intel.com): support BC formats on Metal and OpenGL backend +DAWN_INSTANTIATE_TEST(CompressedTextureBCFormatTest, D3D12Backend, VulkanBackend); diff --git a/src/tests/unittests/d3d12/CopySplitTests.cpp b/src/tests/unittests/d3d12/CopySplitTests.cpp index 5ad16042f5..527ee07f64 100644 --- a/src/tests/unittests/d3d12/CopySplitTests.cpp +++ b/src/tests/unittests/d3d12/CopySplitTests.cpp @@ -14,11 +14,12 @@ #include -#include "dawn_native/d3d12/d3d12_platform.h" -#include "dawn_native/d3d12/TextureCopySplitter.h" #include "common/Assert.h" #include "common/Constants.h" #include "common/Math.h" +#include "dawn_native/Texture.h" +#include "dawn_native/d3d12/TextureCopySplitter.h" +#include "dawn_native/d3d12/d3d12_platform.h" using namespace dawn_native::d3d12; @@ -31,7 +32,9 @@ namespace { uint32_t width; uint32_t height; uint32_t depth; - uint32_t texelSize; + uint32_t texelBlockSizeInBytes; + uint32_t blockWidth = 1; + uint32_t blockHeight = 1; }; struct BufferSpec { @@ -116,15 +119,25 @@ namespace { void ValidateBufferOffset(const TextureSpec& textureSpec, const BufferSpec& bufferSpec, const TextureCopySplit& copySplit) { ASSERT_TRUE(copySplit.count > 0); + uint32_t texelsPerBlock = textureSpec.blockWidth * textureSpec.blockHeight; for (uint32_t i = 0; i < copySplit.count; ++i) { const auto& copy = copySplit.copies[i]; - uint32_t rowPitchInTexels = bufferSpec.rowPitch / textureSpec.texelSize; - uint32_t slicePitchInTexels = rowPitchInTexels * bufferSpec.imageHeight; - uint32_t absoluteTexelOffset = copySplit.offset / textureSpec.texelSize + copy.bufferOffset.x + copy.bufferOffset.y * rowPitchInTexels + copy.bufferOffset.z * slicePitchInTexels; + uint32_t rowPitchInTexels = + bufferSpec.rowPitch / textureSpec.texelBlockSizeInBytes * texelsPerBlock; + uint32_t slicePitchInTexels = + rowPitchInTexels * (bufferSpec.imageHeight / textureSpec.blockHeight); + uint32_t absoluteTexelOffset = + copySplit.offset / textureSpec.texelBlockSizeInBytes * texelsPerBlock + + copy.bufferOffset.x / textureSpec.blockWidth * texelsPerBlock + + copy.bufferOffset.y / textureSpec.blockHeight * rowPitchInTexels + + copy.bufferOffset.z * slicePitchInTexels; - ASSERT(absoluteTexelOffset >= bufferSpec.offset / textureSpec.texelSize); - uint32_t relativeTexelOffset = absoluteTexelOffset - bufferSpec.offset / textureSpec.texelSize; + ASSERT(absoluteTexelOffset >= + bufferSpec.offset / textureSpec.texelBlockSizeInBytes * texelsPerBlock); + uint32_t relativeTexelOffset = + absoluteTexelOffset - + bufferSpec.offset / textureSpec.texelBlockSizeInBytes * texelsPerBlock; uint32_t z = relativeTexelOffset / slicePitchInTexels; uint32_t y = (relativeTexelOffset % slicePitchInTexels) / rowPitchInTexels; @@ -147,9 +160,9 @@ namespace { std::ostream& operator<<(std::ostream& os, const TextureSpec& textureSpec) { os << "TextureSpec(" - << "[(" << textureSpec.x << ", " << textureSpec.y << ", " << textureSpec.z << "), (" << textureSpec.width << ", " << textureSpec.height << ", " << textureSpec.depth << ")], " - << textureSpec.texelSize - << ")"; + << "[(" << textureSpec.x << ", " << textureSpec.y << ", " << textureSpec.z << "), (" + << textureSpec.width << ", " << textureSpec.height << ", " << textureSpec.depth << ")], " + << textureSpec.texelBlockSizeInBytes << ")"; return os; } @@ -186,32 +199,62 @@ namespace { {59, 13, 0, 257, 31, 1, 4}, {17, 73, 0, 17, 93, 1, 4}, {17, 73, 59, 17, 93, 99, 4}, + + {0, 0, 0, 4, 4, 1, 8, 4, 4}, + {64, 16, 0, 4, 4, 1, 8, 4, 4}, + {64, 16, 8, 4, 4, 1, 8, 4, 4}, + {0, 0, 0, 4, 4, 1, 16, 4, 4}, + {64, 16, 0, 4, 4, 1, 16, 4, 4}, + {64, 16, 8, 4, 4, 1, 16, 4, 4}, + + {0, 0, 0, 1024, 1024, 1, 8, 4, 4}, + {256, 512, 0, 1024, 1024, 1, 8, 4, 4}, + {64, 48, 0, 1024, 1024, 1, 8, 4, 4}, + {64, 48, 16, 1024, 1024, 1, 8, 4, 4}, + {0, 0, 0, 1024, 1024, 1, 16, 4, 4}, + {256, 512, 0, 1024, 1024, 1, 16, 4, 4}, + {64, 48, 0, 1024, 1024, 1, 4, 16, 4}, + {64, 48, 16, 1024, 1024, 1, 16, 4, 4}, }; // Define base buffer sizes to work with: some offsets aligned, some unaligned. rowPitch is the minimum required std::array BaseBufferSpecs(const TextureSpec& textureSpec) { - uint32_t rowPitch = Align(textureSpec.texelSize * textureSpec.width, kTextureRowPitchAlignment); + uint32_t rowPitch = + Align(textureSpec.texelBlockSizeInBytes * textureSpec.width, kTextureRowPitchAlignment); auto alignNonPow2 = [](uint32_t value, uint32_t size) -> uint32_t { return value == 0 ? 0 : ((value - 1) / size + 1) * size; }; return { - BufferSpec{alignNonPow2(0, textureSpec.texelSize), rowPitch, textureSpec.height}, - BufferSpec{alignNonPow2(512, textureSpec.texelSize), rowPitch, textureSpec.height}, - BufferSpec{alignNonPow2(1024, textureSpec.texelSize), rowPitch, textureSpec.height}, - BufferSpec{alignNonPow2(1024, textureSpec.texelSize), rowPitch, textureSpec.height * 2}, + BufferSpec{alignNonPow2(0, textureSpec.texelBlockSizeInBytes), rowPitch, + textureSpec.height}, + BufferSpec{alignNonPow2(512, textureSpec.texelBlockSizeInBytes), rowPitch, + textureSpec.height}, + BufferSpec{alignNonPow2(1024, textureSpec.texelBlockSizeInBytes), rowPitch, + textureSpec.height}, + BufferSpec{alignNonPow2(1024, textureSpec.texelBlockSizeInBytes), rowPitch, + textureSpec.height * 2}, - BufferSpec{alignNonPow2(32, textureSpec.texelSize), rowPitch, textureSpec.height}, - BufferSpec{alignNonPow2(64, textureSpec.texelSize), rowPitch, textureSpec.height}, - BufferSpec{alignNonPow2(64, textureSpec.texelSize), rowPitch, textureSpec.height * 2}, + BufferSpec{alignNonPow2(32, textureSpec.texelBlockSizeInBytes), rowPitch, + textureSpec.height}, + BufferSpec{alignNonPow2(64, textureSpec.texelBlockSizeInBytes), rowPitch, + textureSpec.height}, + BufferSpec{alignNonPow2(64, textureSpec.texelBlockSizeInBytes), rowPitch, + textureSpec.height * 2}, - BufferSpec{alignNonPow2(31, textureSpec.texelSize), rowPitch, textureSpec.height}, - BufferSpec{alignNonPow2(257, textureSpec.texelSize), rowPitch, textureSpec.height}, - BufferSpec{alignNonPow2(511, textureSpec.texelSize), rowPitch, textureSpec.height}, - BufferSpec{alignNonPow2(513, textureSpec.texelSize), rowPitch, textureSpec.height}, - BufferSpec{alignNonPow2(1023, textureSpec.texelSize), rowPitch, textureSpec.height}, - BufferSpec{alignNonPow2(1023, textureSpec.texelSize), rowPitch, textureSpec.height * 2}, + BufferSpec{alignNonPow2(31, textureSpec.texelBlockSizeInBytes), rowPitch, + textureSpec.height}, + BufferSpec{alignNonPow2(257, textureSpec.texelBlockSizeInBytes), rowPitch, + textureSpec.height}, + BufferSpec{alignNonPow2(511, textureSpec.texelBlockSizeInBytes), rowPitch, + textureSpec.height}, + BufferSpec{alignNonPow2(513, textureSpec.texelBlockSizeInBytes), rowPitch, + textureSpec.height}, + BufferSpec{alignNonPow2(1023, textureSpec.texelBlockSizeInBytes), rowPitch, + textureSpec.height}, + BufferSpec{alignNonPow2(1023, textureSpec.texelBlockSizeInBytes), rowPitch, + textureSpec.height * 2}, }; } @@ -228,9 +271,15 @@ namespace { class CopySplitTest : public testing::Test { protected: TextureCopySplit 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( {textureSpec.x, textureSpec.y, textureSpec.z}, - {textureSpec.width, textureSpec.height, textureSpec.depth}, textureSpec.texelSize, + {textureSpec.width, textureSpec.height, textureSpec.depth}, fakeFormat, bufferSpec.offset, bufferSpec.rowPitch, bufferSpec.imageHeight); ValidateCopySplit(textureSpec, bufferSpec, copySplit); return copySplit; @@ -255,6 +304,9 @@ TEST_F(CopySplitTest, General) { TEST_F(CopySplitTest, TextureWidth) { for (TextureSpec textureSpec : kBaseTextureSpecs) { for (uint32_t val : kCheckValues) { + if (val % textureSpec.blockWidth != 0) { + continue; + } textureSpec.width = val; for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) { @@ -273,6 +325,9 @@ TEST_F(CopySplitTest, TextureWidth) { TEST_F(CopySplitTest, TextureHeight) { for (TextureSpec textureSpec : kBaseTextureSpecs) { for (uint32_t val : kCheckValues) { + if (val % textureSpec.blockHeight != 0) { + continue; + } textureSpec.height = val; for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) { @@ -327,7 +382,7 @@ TEST_F(CopySplitTest, TextureY) { TEST_F(CopySplitTest, TexelSize) { for (TextureSpec textureSpec : kBaseTextureSpecs) { for (uint32_t texelSize : {4, 8, 16, 32, 64}) { - textureSpec.texelSize = texelSize; + textureSpec.texelBlockSizeInBytes = texelSize; for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) { TextureCopySplit copySplit = DoTest(textureSpec, bufferSpec); @@ -346,7 +401,7 @@ TEST_F(CopySplitTest, BufferOffset) { for (TextureSpec textureSpec : kBaseTextureSpecs) { for (BufferSpec bufferSpec : BaseBufferSpecs(textureSpec)) { for (uint32_t val : kCheckValues) { - bufferSpec.offset = textureSpec.texelSize * val; + bufferSpec.offset = textureSpec.texelBlockSizeInBytes * val; TextureCopySplit copySplit = DoTest(textureSpec, bufferSpec); if (HasFatalFailure()) {