Handle Device Lost for Buffer

Bug: dawn:68, chromium:1042998, chromium:1043468
Change-Id: I4faa46b0d2e8f814b9d353a75489d3c8ca0b2e89
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/15340
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Natasha Lee <natlee@microsoft.com>
This commit is contained in:
Natasha Lee
2020-01-28 22:18:58 +00:00
committed by Commit Bot service account
parent f329c78b6c
commit 74f5054ec9
6 changed files with 193 additions and 17 deletions

View File

@@ -34,6 +34,8 @@ static void ToMockDeviceLostCallback(const char* message, void* userdata) {
self->StartExpectDeviceError();
}
static const int fakeUserData = 0;
class DeviceLostTest : public DawnTest {
protected:
void TestSetUp() override {
@@ -52,6 +54,26 @@ class DeviceLostTest : public DawnTest {
EXPECT_CALL(*mockDeviceLostCallback, Call(_, this)).Times(1);
device.LoseForTesting();
}
static void CheckMapWriteFail(WGPUBufferMapAsyncStatus status,
void* data,
uint64_t datalength,
void* userdata) {
EXPECT_EQ(WGPUBufferMapAsyncStatus_DeviceLost, status);
EXPECT_EQ(nullptr, data);
EXPECT_EQ(0u, datalength);
EXPECT_EQ(&fakeUserData, userdata);
}
static void CheckMapReadFail(WGPUBufferMapAsyncStatus status,
const void* data,
uint64_t datalength,
void* userdata) {
EXPECT_EQ(WGPUBufferMapAsyncStatus_DeviceLost, status);
EXPECT_EQ(nullptr, data);
EXPECT_EQ(0u, datalength);
EXPECT_EQ(&fakeUserData, userdata);
}
};
// Test that DeviceLostCallback is invoked when LostForTestimg is called
@@ -212,4 +234,127 @@ TEST_P(DeviceLostTest, TickFails) {
ASSERT_DEVICE_ERROR(device.Tick());
}
DAWN_INSTANTIATE_TEST(DeviceLostTest, D3D12Backend, VulkanBackend);
// Test that CreateBuffer fails when device is lost
TEST_P(DeviceLostTest, CreateBufferFails) {
SetCallbackAndLoseForTesting();
wgpu::BufferDescriptor bufferDescriptor;
bufferDescriptor.size = sizeof(float);
bufferDescriptor.usage = wgpu::BufferUsage::CopySrc;
ASSERT_DEVICE_ERROR(device.CreateBuffer(&bufferDescriptor));
}
// Test that buffer.MapWriteAsync fails after device is lost
TEST_P(DeviceLostTest, BufferMapWriteAsyncFails) {
wgpu::BufferDescriptor bufferDescriptor;
bufferDescriptor.size = sizeof(float);
bufferDescriptor.usage = wgpu::BufferUsage::MapWrite;
wgpu::Buffer buffer = device.CreateBuffer(&bufferDescriptor);
SetCallbackAndLoseForTesting();
ASSERT_DEVICE_ERROR(buffer.MapWriteAsync(CheckMapWriteFail, const_cast<int*>(&fakeUserData)));
}
// Test that buffer.MapWriteAsync calls back with device loss status
TEST_P(DeviceLostTest, BufferMapWriteAsyncBeforeLossFails) {
wgpu::BufferDescriptor bufferDescriptor;
bufferDescriptor.size = sizeof(float);
bufferDescriptor.usage = wgpu::BufferUsage::MapWrite;
wgpu::Buffer buffer = device.CreateBuffer(&bufferDescriptor);
buffer.MapWriteAsync(CheckMapWriteFail, const_cast<int*>(&fakeUserData));
SetCallbackAndLoseForTesting();
}
// Test that buffer.Unmap fails after device is lost
TEST_P(DeviceLostTest, BufferUnmapFails) {
wgpu::BufferDescriptor bufferDescriptor;
bufferDescriptor.size = sizeof(float);
bufferDescriptor.usage = wgpu::BufferUsage::MapWrite;
wgpu::Buffer buffer = device.CreateBuffer(&bufferDescriptor);
wgpu::CreateBufferMappedResult result = device.CreateBufferMapped(&bufferDescriptor);
SetCallbackAndLoseForTesting();
ASSERT_DEVICE_ERROR(result.buffer.Unmap());
}
// Test that CreateBufferMapped fails after device is lost
TEST_P(DeviceLostTest, CreateBufferMappedFails) {
wgpu::BufferDescriptor bufferDescriptor;
bufferDescriptor.size = sizeof(float);
bufferDescriptor.usage = wgpu::BufferUsage::MapWrite;
SetCallbackAndLoseForTesting();
ASSERT_DEVICE_ERROR(device.CreateBufferMapped(&bufferDescriptor));
}
// Test that CreateBufferMappedAsync fails after device is lost
TEST_P(DeviceLostTest, CreateBufferMappedAsyncFails) {
wgpu::BufferDescriptor bufferDescriptor;
bufferDescriptor.size = sizeof(float);
bufferDescriptor.usage = wgpu::BufferUsage::MapWrite;
SetCallbackAndLoseForTesting();
struct ResultInfo {
wgpu::CreateBufferMappedResult result;
bool done = false;
} resultInfo;
ASSERT_DEVICE_ERROR(device.CreateBufferMappedAsync(
&bufferDescriptor,
[](WGPUBufferMapAsyncStatus status, WGPUCreateBufferMappedResult result, void* userdata) {
auto* resultInfo = static_cast<ResultInfo*>(userdata);
EXPECT_EQ(WGPUBufferMapAsyncStatus_DeviceLost, status);
EXPECT_NE(nullptr, result.data);
resultInfo->result.buffer = wgpu::Buffer::Acquire(result.buffer);
resultInfo->result.data = result.data;
resultInfo->result.dataLength = result.dataLength;
resultInfo->done = true;
},
&resultInfo));
while (!resultInfo.done) {
ASSERT_DEVICE_ERROR(WaitABit());
}
ASSERT_DEVICE_ERROR(resultInfo.result.buffer.Unmap());
}
// Test that BufferMapReadAsync fails after device is lost
TEST_P(DeviceLostTest, BufferMapReadAsyncFails) {
wgpu::BufferDescriptor bufferDescriptor;
bufferDescriptor.size = sizeof(float);
bufferDescriptor.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;
wgpu::Buffer buffer = device.CreateBuffer(&bufferDescriptor);
SetCallbackAndLoseForTesting();
ASSERT_DEVICE_ERROR(buffer.MapReadAsync(CheckMapReadFail, const_cast<int*>(&fakeUserData)));
}
// Test that BufferMapReadAsync calls back with device lost status when device lost after map read
TEST_P(DeviceLostTest, BufferMapReadAsyncBeforeLossFails) {
wgpu::BufferDescriptor bufferDescriptor;
bufferDescriptor.size = sizeof(float);
bufferDescriptor.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;
wgpu::Buffer buffer = device.CreateBuffer(&bufferDescriptor);
buffer.MapReadAsync(CheckMapReadFail, const_cast<int*>(&fakeUserData));
SetCallbackAndLoseForTesting();
}
// Test that SetSubData fails after device is lost
TEST_P(DeviceLostTest, SetSubDataFails) {
wgpu::BufferDescriptor bufferDescriptor;
bufferDescriptor.size = sizeof(float);
bufferDescriptor.usage = wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst;
wgpu::Buffer buffer = device.CreateBuffer(&bufferDescriptor);
SetCallbackAndLoseForTesting();
std::array<float, 1> data = {12};
ASSERT_DEVICE_ERROR(buffer.SetSubData(0, sizeof(float), data.data()));
}
DAWN_INSTANTIATE_TEST(DeviceLostTest, D3D12Backend, VulkanBackend);