mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-14 15:46:28 +00:00
Handle OOM buffer allocations better
This CL checks buffer sizes before creating map read/write handles. It is an error to map a buffer that can't be addressed on the CPU. It also changes client-side synchronous errors on mapAsync to be normal map failures, and not device lost errors. These should be recoverable. The CL adds additional testing for really large, but not UINT64_MAX buffers, and fixes a VVL warning when buffer allocations exceed the size of their memory heap. Bug: dawn:450, dawn:398, chromium:1014740 Change-Id: Ieb34c04c3d01c429b7e3b7810729d5e91ecb6270 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/22626 Commit-Queue: Austin Eng <enga@chromium.org> Reviewed-by: Corentin Wallez <cwallez@chromium.org>
This commit is contained in:
committed by
Commit Bot service account
parent
c3c2c9b6b0
commit
cf1fdf413c
@@ -463,17 +463,6 @@ TEST_P(CreateBufferMappedTests, CreateThenMapBeforeUnmapFailure) {
|
||||
EXPECT_BUFFER_U32_EQ(myData, result.buffer, 0);
|
||||
}
|
||||
|
||||
// Test that creating a very large buffers fails gracefully.
|
||||
TEST_P(CreateBufferMappedTests, LargeBufferFails) {
|
||||
// TODO(http://crbug.com/dawn/27): Missing support.
|
||||
DAWN_SKIP_TEST_IF(IsOpenGL());
|
||||
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
descriptor.size = std::numeric_limits<uint64_t>::max();
|
||||
descriptor.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;
|
||||
ASSERT_DEVICE_ERROR(device.CreateBuffer(&descriptor));
|
||||
}
|
||||
|
||||
// Test that creating a zero-sized buffer mapped is allowed.
|
||||
TEST_P(CreateBufferMappedTests, ZeroSized) {
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
@@ -534,14 +523,148 @@ TEST_P(BufferTests, ZeroSizedBuffer) {
|
||||
}
|
||||
|
||||
// Test that creating a very large buffers fails gracefully.
|
||||
TEST_P(BufferTests, LargeBufferFails) {
|
||||
TEST_P(BufferTests, CreateBufferOOM) {
|
||||
// TODO(http://crbug.com/dawn/27): Missing support.
|
||||
DAWN_SKIP_TEST_IF(IsOpenGL());
|
||||
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
descriptor.usage = wgpu::BufferUsage::CopyDst;
|
||||
|
||||
descriptor.size = std::numeric_limits<uint64_t>::max();
|
||||
descriptor.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;
|
||||
ASSERT_DEVICE_ERROR(device.CreateBuffer(&descriptor));
|
||||
|
||||
// UINT64_MAX may be special cased. Test a smaller, but really large buffer also fails
|
||||
// This hangs on the Metal AMD driver
|
||||
if (!(IsMetal() && IsAMD())) {
|
||||
descriptor.size = 1ull << 50;
|
||||
ASSERT_DEVICE_ERROR(device.CreateBuffer(&descriptor));
|
||||
}
|
||||
}
|
||||
|
||||
// Test that a very large CreateBufferMapped fails gracefully.
|
||||
TEST_P(BufferTests, CreateBufferMappedOOM) {
|
||||
// TODO(http://crbug.com/dawn/27): Missing support.
|
||||
DAWN_SKIP_TEST_IF(IsOpenGL());
|
||||
|
||||
// Test non-mappable buffer
|
||||
{
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
descriptor.size = 4;
|
||||
descriptor.usage = wgpu::BufferUsage::CopyDst;
|
||||
|
||||
// Control: test a small buffer works.
|
||||
device.CreateBufferMapped(&descriptor);
|
||||
|
||||
// Test an enormous buffer fails
|
||||
descriptor.size = std::numeric_limits<uint64_t>::max();
|
||||
ASSERT_DEVICE_ERROR(device.CreateBufferMapped(&descriptor));
|
||||
|
||||
// UINT64_MAX may be special cased. Test a smaller, but really large buffer also fails
|
||||
// This hangs on the Metal AMD driver
|
||||
if (!(IsMetal() && IsAMD())) {
|
||||
descriptor.size = 1ull << 50;
|
||||
ASSERT_DEVICE_ERROR(device.CreateBufferMapped(&descriptor));
|
||||
}
|
||||
}
|
||||
|
||||
// Test mappable buffer
|
||||
{
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
descriptor.size = 4;
|
||||
descriptor.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::MapWrite;
|
||||
|
||||
// Control: test a small buffer works.
|
||||
device.CreateBufferMapped(&descriptor);
|
||||
|
||||
// Test an enormous buffer fails
|
||||
descriptor.size = std::numeric_limits<uint64_t>::max();
|
||||
ASSERT_DEVICE_ERROR(device.CreateBufferMapped(&descriptor));
|
||||
|
||||
if (!(IsMetal() && IsAMD())) {
|
||||
// UINT64_MAX may be special cased. Test a smaller, but really large buffer also fails
|
||||
descriptor.size = 1ull << 50;
|
||||
ASSERT_DEVICE_ERROR(device.CreateBufferMapped(&descriptor));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Test that mapping an OOM buffer for reading fails gracefully
|
||||
TEST_P(BufferTests, CreateBufferOOMMapReadAsync) {
|
||||
// TODO(http://crbug.com/dawn/27): Missing support.
|
||||
DAWN_SKIP_TEST_IF(IsOpenGL());
|
||||
|
||||
auto RunTest = [this](const wgpu::BufferDescriptor& descriptor) {
|
||||
wgpu::Buffer buffer;
|
||||
ASSERT_DEVICE_ERROR(buffer = device.CreateBuffer(&descriptor));
|
||||
|
||||
bool done = false;
|
||||
ASSERT_DEVICE_ERROR(buffer.MapReadAsync(
|
||||
[](WGPUBufferMapAsyncStatus status, const void* ptr, uint64_t dataLength,
|
||||
void* userdata) {
|
||||
EXPECT_EQ(status, WGPUBufferMapAsyncStatus_Error);
|
||||
EXPECT_EQ(ptr, nullptr);
|
||||
EXPECT_EQ(dataLength, 0u);
|
||||
*static_cast<bool*>(userdata) = true;
|
||||
},
|
||||
&done));
|
||||
|
||||
while (!done) {
|
||||
WaitABit();
|
||||
}
|
||||
};
|
||||
|
||||
// Test an enormous buffer
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
descriptor.usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::MapRead;
|
||||
|
||||
descriptor.size = std::numeric_limits<uint64_t>::max();
|
||||
RunTest(descriptor);
|
||||
|
||||
// UINT64_MAX may be special cased. Test a smaller, but really large buffer also fails
|
||||
// This hangs on the Metal AMD driver
|
||||
if (!(IsMetal() && IsAMD())) {
|
||||
descriptor.size = 1ull << 50;
|
||||
RunTest(descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
// Test that mapping an OOM buffer for reading fails gracefully
|
||||
TEST_P(BufferTests, CreateBufferOOMMapWriteAsync) {
|
||||
// TODO(http://crbug.com/dawn/27): Missing support.
|
||||
DAWN_SKIP_TEST_IF(IsOpenGL());
|
||||
|
||||
auto RunTest = [this](const wgpu::BufferDescriptor& descriptor) {
|
||||
wgpu::Buffer buffer;
|
||||
ASSERT_DEVICE_ERROR(buffer = device.CreateBuffer(&descriptor));
|
||||
|
||||
bool done = false;
|
||||
ASSERT_DEVICE_ERROR(buffer.MapWriteAsync(
|
||||
[](WGPUBufferMapAsyncStatus status, void* ptr, uint64_t dataLength, void* userdata) {
|
||||
EXPECT_EQ(status, WGPUBufferMapAsyncStatus_Error);
|
||||
EXPECT_EQ(ptr, nullptr);
|
||||
EXPECT_EQ(dataLength, 0u);
|
||||
*static_cast<bool*>(userdata) = true;
|
||||
},
|
||||
&done));
|
||||
|
||||
while (!done) {
|
||||
WaitABit();
|
||||
}
|
||||
};
|
||||
|
||||
wgpu::BufferDescriptor descriptor;
|
||||
descriptor.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::MapWrite;
|
||||
|
||||
// Test an enormous buffer
|
||||
descriptor.size = std::numeric_limits<uint64_t>::max();
|
||||
RunTest(descriptor);
|
||||
|
||||
// UINT64_MAX may be special cased. Test a smaller, but really large buffer also fails
|
||||
// This hangs on the Metal AMD driver
|
||||
if (!(IsMetal() && IsAMD())) {
|
||||
descriptor.size = 1ull << 50;
|
||||
RunTest(descriptor);
|
||||
}
|
||||
}
|
||||
|
||||
DAWN_INSTANTIATE_TEST(BufferTests,
|
||||
|
||||
@@ -474,10 +474,9 @@ TEST_F(WireMemoryTransferServiceTests, BufferMapReadHandleCreationFailure) {
|
||||
// Mock a ReadHandle creation failure
|
||||
MockReadHandleCreationFailure();
|
||||
|
||||
// Failed creation of a ReadHandle is a fatal failure and the client synchronously receives a
|
||||
// DEVICE_LOST callback.
|
||||
EXPECT_CALL(*mockBufferMapReadCallback,
|
||||
Call(WGPUBufferMapAsyncStatus_DeviceLost, nullptr, 0, _))
|
||||
// Failed creation of a ReadHandle is a mapping failure and the client synchronously receives
|
||||
// an error callback.
|
||||
EXPECT_CALL(*mockBufferMapReadCallback, Call(WGPUBufferMapAsyncStatus_Error, nullptr, 0, _))
|
||||
.Times(1);
|
||||
|
||||
wgpuBufferMapReadAsync(buffer, ToMockBufferMapReadCallback, nullptr);
|
||||
@@ -716,10 +715,9 @@ TEST_F(WireMemoryTransferServiceTests, BufferMapWriteHandleCreationFailure) {
|
||||
// Mock a WriteHandle creation failure
|
||||
MockWriteHandleCreationFailure();
|
||||
|
||||
// Failed creation of a WriteHandle is a fatal failure and the client synchronously receives a
|
||||
// DEVICE_LOST callback.
|
||||
EXPECT_CALL(*mockBufferMapWriteCallback,
|
||||
Call(WGPUBufferMapAsyncStatus_DeviceLost, nullptr, 0, _))
|
||||
// Failed creation of a WriteHandle is a mapping failure and the client synchronously receives
|
||||
// an error callback.
|
||||
EXPECT_CALL(*mockBufferMapWriteCallback, Call(WGPUBufferMapAsyncStatus_Error, nullptr, 0, _))
|
||||
.Times(1);
|
||||
|
||||
wgpuBufferMapWriteAsync(buffer, ToMockBufferMapWriteCallback, nullptr);
|
||||
|
||||
Reference in New Issue
Block a user