Fix a bug in ComputeTextureCopyBufferSize with empty copySize

This patch fixes a bug in buffer-to-texture and texture-to-buffer copies
when copySize.height == 0 or copySize.depth == 0. Previously we miss the
checks if either copySize.height or copySize.depth is 0 before doing
(copySize.height / blockHeight - 1) and (copySize.depth - 1) thus we
will get incorrect results because of arithmetic overflows.

This patch fixes this bug by adding the missed check and adds the
related regression tests in dawn_unittests

BUG=dawn:453
TEST=dawn_unittests

Change-Id: I970e420c0fa7f0b61c656365bef079c123a59e6a
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/23520
Commit-Queue: Kai Ninomiya <kainino@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
This commit is contained in:
Jiawei Shao 2020-06-19 22:39:53 +00:00 committed by Commit Bot service account
parent f434fdc6ed
commit e5d94c31a0
2 changed files with 15 additions and 0 deletions

View File

@ -198,14 +198,23 @@ namespace dawn_native {
uint32_t rowsPerImage, uint32_t rowsPerImage,
uint32_t* bufferSize) { uint32_t* bufferSize) {
ASSERT(rowsPerImage >= copySize.height); ASSERT(rowsPerImage >= copySize.height);
if (copySize.width == 0 || copySize.height == 0 || copySize.depth == 0) {
*bufferSize = 0;
return {};
}
uint32_t blockByteSize = textureFormat.blockByteSize; uint32_t blockByteSize = textureFormat.blockByteSize;
uint32_t blockWidth = textureFormat.blockWidth; uint32_t blockWidth = textureFormat.blockWidth;
uint32_t blockHeight = textureFormat.blockHeight; uint32_t blockHeight = textureFormat.blockHeight;
// TODO(cwallez@chromium.org): check for overflows // TODO(cwallez@chromium.org): check for overflows
uint32_t slicePitch = bytesPerRow * rowsPerImage / blockWidth; uint32_t slicePitch = bytesPerRow * rowsPerImage / blockWidth;
ASSERT(copySize.height >= 1);
uint32_t sliceSize = bytesPerRow * (copySize.height / blockHeight - 1) + uint32_t sliceSize = bytesPerRow * (copySize.height / blockHeight - 1) +
(copySize.width / blockWidth) * blockByteSize; (copySize.width / blockWidth) * blockByteSize;
ASSERT(copySize.depth >= 1);
*bufferSize = (slicePitch * (copySize.depth - 1)) + sliceSize; *bufferSize = (slicePitch * (copySize.depth - 1)) + sliceSize;
return {}; return {};

View File

@ -364,6 +364,12 @@ TEST_F(CopyCommandTest_B2T, Success) {
// An empty copy touching the side of the texture // An empty copy touching the side of the texture
TestB2TCopy(utils::Expectation::Success, source, 0, 0, 0, destination, 0, {16, 16, 0}, TestB2TCopy(utils::Expectation::Success, source, 0, 0, 0, destination, 0, {16, 16, 0},
{0, 0, 1}); {0, 0, 1});
// An empty copy with depth = 1 and bytesPerRow > 0
TestB2TCopy(utils::Expectation::Success, source, 0, kTextureBytesPerRowAlignment, 0,
destination, 0, {0, 0, 0}, {0, 0, 1});
// An empty copy with height > 0, depth = 0, bytesPerRow > 0 and rowsPerImage > 0
TestB2TCopy(utils::Expectation::Success, source, 0, kTextureBytesPerRowAlignment, 16,
destination, 0, {0, 0, 0}, {0, 1, 0});
} }
} }