diff --git a/src/tests/end2end/CopyTests.cpp b/src/tests/end2end/CopyTests.cpp index 8194cb4cd7..0a5076d5f5 100644 --- a/src/tests/end2end/CopyTests.cpp +++ b/src/tests/end2end/CopyTests.cpp @@ -151,8 +151,8 @@ class CopyTests_T2B : public CopyTests { // Layout for initial data upload to texture. // Some parts of this result are also reused later. const utils::TextureDataCopyLayout copyLayout = - utils::GetTextureDataCopyLayoutForTexture2DAtLevel( - textureSpec.format, textureSpec.textureSize, textureSpec.copyLevel); + utils::GetTextureDataCopyLayoutForTextureAtLevel( + textureSpec.format, textureSpec.textureSize, textureSpec.copyLevel, dimension); // Initialize the source texture std::vector textureArrayData = GetExpectedTextureDataRGBA8(copyLayout); @@ -279,8 +279,8 @@ class CopyTests_B2T : public CopyTests { queue.Submit(1, &commands); const utils::TextureDataCopyLayout copyLayout = - utils::GetTextureDataCopyLayoutForTexture2DAtLevel( - textureSpec.format, textureSpec.textureSize, textureSpec.copyLevel, + utils::GetTextureDataCopyLayoutForTextureAtLevel( + textureSpec.format, textureSpec.textureSize, textureSpec.copyLevel, dimension, bufferSpec.rowsPerImage); uint32_t copyLayer = copySize.depthOrArrayLayers; @@ -367,11 +367,11 @@ class CopyTests_T2T : public CopyTests { // Create an upload buffer and use it to populate the current slice of the texture in // `level` mip level const utils::TextureDataCopyLayout srcDataCopyLayout = - utils::GetTextureDataCopyLayoutForTexture2DAtLevel( + utils::GetTextureDataCopyLayoutForTextureAtLevel( format, {srcSpec.textureSize.width, srcSpec.textureSize.height, copySize.depthOrArrayLayers}, - srcSpec.copyLevel); + srcSpec.copyLevel, srcDimension); // Initialize the source texture const std::vector srcTextureCopyData = GetExpectedTextureData(srcDataCopyLayout); @@ -397,11 +397,11 @@ class CopyTests_T2T : public CopyTests { // Copy the data from the srcSpec.copyOrigin.z-th layer to (srcSpec.copyOrigin.z + // copySize.depthOrArrayLayers)-th layer of dstTexture to outputBuffer const utils::TextureDataCopyLayout dstDataCopyLayout = - utils::GetTextureDataCopyLayoutForTexture2DAtLevel( + utils::GetTextureDataCopyLayoutForTextureAtLevel( format, {dstSpec.textureSize.width, dstSpec.textureSize.height, copySize.depthOrArrayLayers}, - dstSpec.copyLevel); + dstSpec.copyLevel, dstDimension); wgpu::BufferDescriptor outputBufferDescriptor; outputBufferDescriptor.size = dstDataCopyLayout.byteLength; outputBufferDescriptor.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst; @@ -1161,6 +1161,44 @@ TEST_P(CopyTests_T2B, Texture3DCopyHeightIsOneCopyWidthIsSmall) { DoTest(textureSpec, bufferSpec, {kWidth, kHeight, kDepth}, wgpu::TextureDimension::e3D); } +// Test that copying texture 3D array mips with 256-byte aligned sizes works +TEST_P(CopyTests_T2B, Texture3DMipAligned) { + constexpr uint32_t kWidth = 256; + constexpr uint32_t kHeight = 128; + constexpr uint32_t kDepth = 64u; + + TextureSpec defaultTextureSpec; + defaultTextureSpec.textureSize = {kWidth, kHeight, kDepth}; + + for (unsigned int i = 1; i < 6; ++i) { + TextureSpec textureSpec = defaultTextureSpec; + textureSpec.copyLevel = i; + textureSpec.levelCount = i + 1; + + DoTest(textureSpec, MinimumBufferSpec(kWidth >> i, kHeight >> i, kDepth >> i), + {kWidth >> i, kHeight >> i, kDepth >> i}, wgpu::TextureDimension::e3D); + } +} + +// Test that copying texture 3D array mips with 256-byte unaligned sizes works +TEST_P(CopyTests_T2B, Texture3DMipUnaligned) { + constexpr uint32_t kWidth = 261; + constexpr uint32_t kHeight = 123; + constexpr uint32_t kDepth = 69u; + + TextureSpec defaultTextureSpec; + defaultTextureSpec.textureSize = {kWidth, kHeight, kDepth}; + + for (unsigned int i = 1; i < 6; ++i) { + TextureSpec textureSpec = defaultTextureSpec; + textureSpec.copyLevel = i; + textureSpec.levelCount = i + 1; + + DoTest(textureSpec, MinimumBufferSpec(kWidth >> i, kHeight >> i, kDepth >> i), + {kWidth >> i, kHeight >> i, kDepth >> i}, wgpu::TextureDimension::e3D); + } +} + // TODO(yunchao.he@intel.com): add T2B tests for 3D textures, like RowPitch, // RowsPerImage, buffer offset, partial depth range, non-zero level, etc. @@ -1740,6 +1778,44 @@ TEST_P(CopyTests_B2T, Texture3DCopyHeightIsOneCopyWidthIsSmall) { DoTest(textureSpec, bufferSpec, {kWidth, kHeight, kDepth}, wgpu::TextureDimension::e3D); } +// Test that copying texture 3D array mips with 256-byte aligned sizes works +TEST_P(CopyTests_B2T, Texture3DMipAligned) { + constexpr uint32_t kWidth = 256; + constexpr uint32_t kHeight = 128; + constexpr uint32_t kDepth = 64u; + + TextureSpec defaultTextureSpec; + defaultTextureSpec.textureSize = {kWidth, kHeight, kDepth}; + + for (unsigned int i = 1; i < 6; ++i) { + TextureSpec textureSpec = defaultTextureSpec; + textureSpec.copyLevel = i; + textureSpec.levelCount = i + 1; + + DoTest(textureSpec, MinimumBufferSpec(kWidth >> i, kHeight >> i, kDepth >> i), + {kWidth >> i, kHeight >> i, kDepth >> i}, wgpu::TextureDimension::e3D); + } +} + +// Test that copying texture 3D array mips with 256-byte unaligned sizes works +TEST_P(CopyTests_B2T, Texture3DMipUnaligned) { + constexpr uint32_t kWidth = 261; + constexpr uint32_t kHeight = 123; + constexpr uint32_t kDepth = 69u; + + TextureSpec defaultTextureSpec; + defaultTextureSpec.textureSize = {kWidth, kHeight, kDepth}; + + for (unsigned int i = 1; i < 6; ++i) { + TextureSpec textureSpec = defaultTextureSpec; + textureSpec.copyLevel = i; + textureSpec.levelCount = i + 1; + + DoTest(textureSpec, MinimumBufferSpec(kWidth >> i, kHeight >> i, kDepth >> i), + {kWidth >> i, kHeight >> i, kDepth >> i}, wgpu::TextureDimension::e3D); + } +} + // TODO(yunchao.he@intel.com): add more tests like RowPitch, RowsPerImage, buffer offset, partial // depth range, non-zero level, etc. diff --git a/src/tests/end2end/CopyTextureForBrowserTests.cpp b/src/tests/end2end/CopyTextureForBrowserTests.cpp index 1cce29a455..5bd197c51f 100644 --- a/src/tests/end2end/CopyTextureForBrowserTests.cpp +++ b/src/tests/end2end/CopyTextureForBrowserTests.cpp @@ -247,7 +247,7 @@ class CopyTextureForBrowserTests : public DawnTest { wgpu::Texture srcTexture = device.CreateTexture(&srcDescriptor); const utils::TextureDataCopyLayout srcCopyLayout = - utils::GetTextureDataCopyLayoutForTexture2DAtLevel( + utils::GetTextureDataCopyLayoutForTextureAtLevel( kTextureFormat, {srcSpec.textureSize.width, srcSpec.textureSize.height, copySize.depthOrArrayLayers}, @@ -293,7 +293,7 @@ class CopyTextureForBrowserTests : public DawnTest { if (testSubRectCopy) { // For subrect copy tests, dst texture use kTextureFormat always. const utils::TextureDataCopyLayout dstCopyLayout = - utils::GetTextureDataCopyLayoutForTexture2DAtLevel( + utils::GetTextureDataCopyLayoutForTextureAtLevel( kTextureFormat, {dstSpec.textureSize.width, dstSpec.textureSize.height, copySize.depthOrArrayLayers}, diff --git a/src/utils/TestUtils.cpp b/src/utils/TestUtils.cpp index cac3a1ac9c..433ef3730f 100644 --- a/src/utils/TestUtils.cpp +++ b/src/utils/TestUtils.cpp @@ -31,10 +31,11 @@ namespace utils { return Align(bytesPerBlock * (width / blockWidth), kTextureBytesPerRowAlignment); } - TextureDataCopyLayout GetTextureDataCopyLayoutForTexture2DAtLevel( + TextureDataCopyLayout GetTextureDataCopyLayoutForTextureAtLevel( wgpu::TextureFormat format, wgpu::Extent3D textureSizeAtLevel0, uint32_t mipmapLevel, + wgpu::TextureDimension dimension, uint32_t rowsPerImage) { // Compressed texture formats not supported in this function yet. ASSERT(utils::GetTextureFormatBlockWidth(format) == 1); @@ -45,6 +46,11 @@ namespace utils { std::max(textureSizeAtLevel0.height >> mipmapLevel, 1u), textureSizeAtLevel0.depthOrArrayLayers}; + if (dimension == wgpu::TextureDimension::e3D) { + layout.mipSize.depthOrArrayLayers = + std::max(textureSizeAtLevel0.depthOrArrayLayers >> mipmapLevel, 1u); + } + layout.bytesPerRow = GetMinimumBytesPerRow(format, layout.mipSize.width); if (rowsPerImage == wgpu::kCopyStrideUndefined) { diff --git a/src/utils/TestUtils.h b/src/utils/TestUtils.h index 013de67d80..d611124175 100644 --- a/src/utils/TestUtils.h +++ b/src/utils/TestUtils.h @@ -31,10 +31,11 @@ namespace utils { }; uint32_t GetMinimumBytesPerRow(wgpu::TextureFormat format, uint32_t width); - TextureDataCopyLayout GetTextureDataCopyLayoutForTexture2DAtLevel( + TextureDataCopyLayout GetTextureDataCopyLayoutForTextureAtLevel( wgpu::TextureFormat format, wgpu::Extent3D textureSizeAtLevel0, uint32_t mipmapLevel, + wgpu::TextureDimension dimension = wgpu::TextureDimension::e2D, uint32_t rowsPerImage = wgpu::kCopyStrideUndefined); uint64_t RequiredBytesInCopy(uint64_t bytesPerRow,