Add validation on the buffer-to-buffer copies within same buffer

This patch adds the validation on the buffer-to-buffer copies within the
same buffer. When the source and destination buffer are the same one in
CopyBufferToBuffer(), the copy region cannot overlap or it will cause
undefined behaviors on Metal and Vulkan.

BUG=dawn:17
TEST=dawn_unittests, dawn_end2end_tests

Change-Id: I63ab790787ec0a973ae22787a9348bddfb6a5373
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/21602
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
This commit is contained in:
Jiawei Shao
2020-05-13 00:17:15 +00:00
committed by Commit Bot service account
parent fce44b5fe1
commit f4df7916ca
3 changed files with 127 additions and 0 deletions

View File

@@ -266,6 +266,61 @@ TEST_F(CopyCommandTest_B2B, BuffersInErrorState) {
}
}
// Test B2B copies within same buffer.
TEST_F(CopyCommandTest_B2B, CopyWithinSameBuffer) {
constexpr uint32_t kBufferSize = 16u;
wgpu::Buffer buffer =
CreateBuffer(kBufferSize, wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst);
// When srcOffset < dstOffset, and srcOffset + copySize > dstOffset, it is not allowed because
// the copy regions are overlapping.
{
constexpr uint32_t kSrcOffset = 0u;
constexpr uint32_t kDstOffset = 4u;
constexpr uint32_t kCopySize = 8u;
ASSERT(kDstOffset > kSrcOffset && kDstOffset < kSrcOffset + kCopySize);
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.CopyBufferToBuffer(buffer, kSrcOffset, buffer, kDstOffset, kCopySize);
ASSERT_DEVICE_ERROR(encoder.Finish());
}
// When srcOffset < dstOffset, and srcOffset + copySize == dstOffset, it is allowed
// because the copy regions are not overlapping.
{
constexpr uint32_t kSrcOffset = 0u;
constexpr uint32_t kDstOffset = 8u;
constexpr uint32_t kCopySize = kDstOffset - kSrcOffset;
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.CopyBufferToBuffer(buffer, kSrcOffset, buffer, kDstOffset, kCopySize);
encoder.Finish();
}
// When srcOffset > dstOffset, and srcOffset < dstOffset + copySize, it is not allowed because
// the copy regions are overlapping.
{
constexpr uint32_t kSrcOffset = 4u;
constexpr uint32_t kDstOffset = 0u;
constexpr uint32_t kCopySize = 8u;
ASSERT(kSrcOffset > kDstOffset && kSrcOffset < kDstOffset + kCopySize);
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.CopyBufferToBuffer(buffer, kSrcOffset, buffer, kDstOffset, kCopySize);
ASSERT_DEVICE_ERROR(encoder.Finish());
}
// When srcOffset > dstOffset, and srcOffset + copySize == dstOffset, it is allowed
// because the copy regions are not overlapping.
{
constexpr uint32_t kSrcOffset = 8u;
constexpr uint32_t kDstOffset = 0u;
constexpr uint32_t kCopySize = kSrcOffset - kDstOffset;
wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
encoder.CopyBufferToBuffer(buffer, kSrcOffset, buffer, kDstOffset, kCopySize);
encoder.Finish();
}
}
class CopyCommandTest_B2T : public CopyCommandTest {};
// Test a successfull B2T copy