Add data verification for e2e tests in RequiredBufferSizeInCopyTests.cpp

When we try to work around the bug exposed by tests in this file,
it is necessary to make D3D12 runtime happy and no validatin error
is reported. It is also essential to verify the correctness of
buffer/texture data after T2B/B2T copy whether workaround is applied
or not.

Bug: dawn:1289
Change-Id: I0d86375c513ffd579fdebc786d00e9eccb60cc10
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/86511
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Yunchao He <yunchao.he@intel.com>
This commit is contained in:
Yunchao He 2022-04-14 14:44:40 +00:00 committed by Dawn LUCI CQ
parent 384ccb9b3a
commit 3dc4a34385
1 changed files with 77 additions and 29 deletions

View File

@ -17,14 +17,31 @@
#include "dawn/utils/TestUtils.h"
#include "dawn/utils/WGPUHelpers.h"
enum class Type { B2TCopy, T2BCopy };
constexpr static wgpu::Extent3D kCopySize = {1, 1, 2};
constexpr static uint64_t kOffset = 0;
constexpr static uint64_t kBytesPerRow = 256;
constexpr static uint64_t kRowsPerImagePadding = 1;
constexpr static uint64_t kRowsPerImage = kRowsPerImagePadding + kCopySize.height;
constexpr static wgpu::TextureFormat kFormat = wgpu::TextureFormat::RGBA8Unorm;
constexpr static uint32_t kBytesPerBlock = 4;
namespace {
enum class Type { B2TCopy, T2BCopy };
std::ostream& operator<<(std::ostream& o, Type copyType) {
switch (copyType) {
case Type::B2TCopy:
o << "B2TCopy";
break;
case Type::T2BCopy:
o << "T2BCopy";
break;
}
return o;
}
DAWN_TEST_PARAM_STRUCT(RequiredBufferSizeInCopyTestsParams, Type);
} // namespace
// Tests in this file are used to expose an error on D3D12 about required minimum buffer size.
// See detailed bug reports at crbug.com/dawn/1278, 1288, 1289.
@ -51,9 +68,10 @@ constexpr static wgpu::TextureFormat kFormat = wgpu::TextureFormat::RGBA8Unorm;
// image. It does respect bytesPerRowPadding in the last row and doesn't require storage for
// that part, though.
class RequiredBufferSizeInCopyTests : public DawnTest {
class RequiredBufferSizeInCopyTests
: public DawnTestWithParams<RequiredBufferSizeInCopyTestsParams> {
protected:
void DoTest(const uint64_t bufferSize, Type copyType) {
void DoTest(const uint64_t bufferSize) {
wgpu::BufferDescriptor descriptor;
descriptor.size = bufferSize;
descriptor.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst;
@ -71,57 +89,87 @@ class RequiredBufferSizeInCopyTests : public DawnTest {
wgpu::ImageCopyBuffer imageCopyBuffer =
utils::CreateImageCopyBuffer(buffer, kOffset, kBytesPerRow, kRowsPerImage);
// Initialize copied data and set expected data for buffer and texture.
ASSERT(sizeof(uint32_t) == kBytesPerBlock);
uint32_t numOfBufferElements = bufferSize / kBytesPerBlock;
std::vector<uint32_t> data(numOfBufferElements, 1);
std::vector<uint32_t> expectedBufferData(numOfBufferElements, 0);
std::vector<uint32_t> expectedTextureData(kCopySize.depthOrArrayLayers, 0);
// Initialize the first element on every image to be 0x80808080
uint64_t imageSize = kBytesPerRow * kRowsPerImage;
ASSERT(bufferSize >= (imageSize * (kCopySize.depthOrArrayLayers - 1) + kBytesPerBlock));
uint32_t numOfImageElements = imageSize / kBytesPerBlock;
for (uint32_t i = 0; i < kCopySize.depthOrArrayLayers; ++i) {
data[i * numOfImageElements] = 0x80808080;
expectedBufferData[i * numOfImageElements] = 0x80808080;
expectedTextureData[i] = 0x80808080;
}
// Do B2T copy or T2B copy
wgpu::CommandEncoder encoder = this->device.CreateCommandEncoder();
switch (copyType) {
switch (GetParam().mType) {
case Type::T2BCopy: {
std::vector<uint32_t> expectedData(bufferSize / 4, 1);
wgpu::TextureDataLayout textureDataLayout =
utils::CreateTextureDataLayout(kOffset, kBytesPerRow, kRowsPerImage);
queue.WriteTexture(&imageCopyTexture, expectedData.data(), bufferSize,
&textureDataLayout, &kCopySize);
queue.WriteTexture(&imageCopyTexture, data.data(), bufferSize, &textureDataLayout,
&kCopySize);
encoder.CopyTextureToBuffer(&imageCopyTexture, &imageCopyBuffer, &kCopySize);
break;
}
case Type::B2TCopy:
queue.WriteBuffer(buffer, 0, data.data(), bufferSize);
encoder.CopyBufferToTexture(&imageCopyBuffer, &imageCopyTexture, &kCopySize);
break;
}
wgpu::CommandBuffer commands = encoder.Finish();
queue.Submit(1, &commands);
// Verify the data in buffer (T2B copy) or texture (B2T copy)
switch (GetParam().mType) {
case Type::T2BCopy:
EXPECT_BUFFER_U32_RANGE_EQ(expectedBufferData.data(), buffer, 0, bufferSize / 4);
break;
case Type::B2TCopy:
EXPECT_TEXTURE_EQ(expectedTextureData.data(), texture, {0, 0, 0}, kCopySize);
break;
}
}
};
TEST_P(RequiredBufferSizeInCopyTests, T2BCopyWithAbundantBufferSize) {
// The buffer contains full data on the last image and has storage for all kinds of paddings.
TEST_P(RequiredBufferSizeInCopyTests, AbundantBufferSize) {
uint64_t size = kOffset + kBytesPerRow * kRowsPerImage * kCopySize.depthOrArrayLayers;
DoTest(size, Type::T2BCopy);
DoTest(size);
}
TEST_P(RequiredBufferSizeInCopyTests, B2TCopyWithAbundantBufferSize) {
uint64_t size = kOffset + kBytesPerRow * kRowsPerImage * kCopySize.depthOrArrayLayers;
DoTest(size, Type::B2TCopy);
// The buffer has storage for rowsPerImage paddings on the last image but not bytesPerRow
// paddings on the last row, which is exactly what D3D12 requires. See the comments at the
// beginning of class RequiredBufferSizeInCopyTests for details.
TEST_P(RequiredBufferSizeInCopyTests, BufferSizeOnBoundary) {
uint64_t size = kOffset + kBytesPerRow * kRowsPerImage * (kCopySize.depthOrArrayLayers - 1) +
kBytesPerRow * (kRowsPerImage - 1) + kBytesPerBlock * kCopySize.width;
DoTest(size);
// TODO(crbug.com/dawn/1278, 1288, 1289): Required buffer size for copy is wrong on D3D12.
DAWN_SUPPRESS_TEST_IF(IsD3D12());
size -= kBytesPerBlock;
DoTest(size);
}
TEST_P(RequiredBufferSizeInCopyTests, T2BCopyWithMininumBufferSize) {
// The buffer doesn't have storage for any paddings on the last image. WebGPU spec doesn't require
// storage for these paddings, and the copy operation will never access to these paddings. So it
// should work.
TEST_P(RequiredBufferSizeInCopyTests, MininumBufferSize) {
// TODO(crbug.com/dawn/1278, 1288, 1289): Required buffer size for copy is wrong on D3D12.
DAWN_SUPPRESS_TEST_IF(IsD3D12());
uint64_t size =
kOffset + utils::RequiredBytesInCopy(kBytesPerRow, kRowsPerImage, kCopySize, kFormat);
DoTest(size, Type::T2BCopy);
DoTest(size);
}
TEST_P(RequiredBufferSizeInCopyTests, B2TCopyWithMininumBufferSize) {
// TODO(crbug.com/dawn/1278, 1288, 1289): Required buffer size for copy is wrong on D3D12.
DAWN_SUPPRESS_TEST_IF(IsD3D12());
uint64_t size =
kOffset + utils::RequiredBytesInCopy(kBytesPerRow, kRowsPerImage, kCopySize, kFormat);
DoTest(size, Type::B2TCopy);
}
DAWN_INSTANTIATE_TEST(RequiredBufferSizeInCopyTests,
D3D12Backend(),
MetalBackend(),
OpenGLBackend(),
OpenGLESBackend(),
VulkanBackend());
DAWN_INSTANTIATE_TEST_P(RequiredBufferSizeInCopyTests,
{D3D12Backend(), MetalBackend(), OpenGLBackend(), OpenGLESBackend(),
VulkanBackend()},
{Type::T2BCopy, Type::B2TCopy});