From 67851d902192f9059f0a39a995af580c7d23fad9 Mon Sep 17 00:00:00 2001 From: Austin Eng Date: Mon, 10 May 2021 17:42:41 +0000 Subject: [PATCH] Validate that 3D texture copies cannot be between the same subresource Bug: dawn:547 Change-Id: I747ccdb895121292e527acc385d69697bc86d8b2 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/50240 Commit-Queue: Austin Eng Reviewed-by: Yunchao He --- src/dawn_native/CommandValidation.cpp | 11 +++-- .../CopyCommandsValidationTests.cpp | 48 +++++++++++++++++++ 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/src/dawn_native/CommandValidation.cpp b/src/dawn_native/CommandValidation.cpp index 9b647db222..f99466383b 100644 --- a/src/dawn_native/CommandValidation.cpp +++ b/src/dawn_native/CommandValidation.cpp @@ -421,12 +421,13 @@ namespace dawn_native { } if (src.texture == dst.texture && src.mipLevel == dst.mipLevel) { - ASSERT(src.texture->GetDimension() == wgpu::TextureDimension::e2D && - dst.texture->GetDimension() == wgpu::TextureDimension::e2D); - if (IsRangeOverlapped(src.origin.z, dst.origin.z, copySize.depthOrArrayLayers)) { + wgpu::TextureDimension dimension = src.texture->GetDimension(); + ASSERT(dimension != wgpu::TextureDimension::e1D); + if ((dimension == wgpu::TextureDimension::e2D && + IsRangeOverlapped(src.origin.z, dst.origin.z, copySize.depthOrArrayLayers)) || + dimension == wgpu::TextureDimension::e3D) { return DAWN_VALIDATION_ERROR( - "Copy subresources cannot be overlapped when copying within the same " - "texture."); + "Cannot copy between overlapping subresources of the same texture."); } } diff --git a/src/tests/unittests/validation/CopyCommandsValidationTests.cpp b/src/tests/unittests/validation/CopyCommandsValidationTests.cpp index 29b664acdb..dbbc3327c3 100644 --- a/src/tests/unittests/validation/CopyCommandsValidationTests.cpp +++ b/src/tests/unittests/validation/CopyCommandsValidationTests.cpp @@ -50,6 +50,24 @@ class CopyCommandTest : public ValidationTest { return tex; } + wgpu::Texture Create3DTexture(uint32_t width, + uint32_t height, + uint32_t depth, + uint32_t mipLevelCount, + wgpu::TextureFormat format, + wgpu::TextureUsage usage) { + wgpu::TextureDescriptor descriptor; + descriptor.dimension = wgpu::TextureDimension::e3D; + descriptor.size.width = width; + descriptor.size.height = height; + descriptor.size.depthOrArrayLayers = depth; + descriptor.format = format; + descriptor.mipLevelCount = mipLevelCount; + descriptor.usage = usage; + wgpu::Texture tex = device.CreateTexture(&descriptor); + return tex; + } + uint32_t BufferSizeForTextureCopy( uint32_t width, uint32_t height, @@ -1900,6 +1918,36 @@ TEST_F(CopyCommandTest_T2T, CopyWithinSameTexture) { // Copy between different mipmap levels and array slices is allowed. TestT2TCopy(utils::Expectation::Success, texture, 0, {0, 0, 1}, texture, 1, {1, 1, 0}, {1, 1, 1}); + + // Copy between 3D texture of both overlapping depth ranges is not allowed. + { + wgpu::Texture texture3D = + Create3DTexture(32, 32, 4, 2, wgpu::TextureFormat::RGBA8Unorm, + wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst); + + constexpr uint32_t kMipmapLevel = 0; + constexpr wgpu::Origin3D kSrcOrigin = {0, 0, 0}; + constexpr wgpu::Origin3D kDstOrigin = {0, 0, 1}; + constexpr wgpu::Extent3D kCopyExtent = {4, 4, 2}; + + TestT2TCopy(utils::Expectation::Failure, texture3D, kMipmapLevel, kSrcOrigin, texture3D, + kMipmapLevel, kDstOrigin, kCopyExtent); + } + + // Copy between 3D texture of both non-overlapping depth ranges is not allowed. + { + wgpu::Texture texture3D = + Create3DTexture(32, 32, 4, 2, wgpu::TextureFormat::RGBA8Unorm, + wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst); + + constexpr uint32_t kMipmapLevel = 0; + constexpr wgpu::Origin3D kSrcOrigin = {0, 0, 0}; + constexpr wgpu::Origin3D kDstOrigin = {0, 0, 2}; + constexpr wgpu::Extent3D kCopyExtent = {4, 4, 1}; + + TestT2TCopy(utils::Expectation::Failure, texture3D, kMipmapLevel, kSrcOrigin, texture3D, + kMipmapLevel, kDstOrigin, kCopyExtent); + } } class CopyCommandTest_CompressedTextureFormats : public CopyCommandTest {