[dawn] Add more tests of buffer mapping and device loss/destroy Bug: 42240407, 492139412 Change-Id: Ifef5b6a0e0219c7833a364b629d03b357ed42b89 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/297055 Reviewed-by: Loko Kung <lokokung@google.com> Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn/tests/end2end/DeviceLostTests.cpp b/src/dawn/tests/end2end/DeviceLostTests.cpp index a2befd3..df99544 100644 --- a/src/dawn/tests/end2end/DeviceLostTests.cpp +++ b/src/dawn/tests/end2end/DeviceLostTests.cpp
@@ -407,6 +407,9 @@ ExpectObjectIsError(buffer); ASSERT_NE(buffer.GetMappedRange(), nullptr); + + // Write to the range as it should still point to valid memory. + *static_cast<uint32_t*>(buffer.GetMappedRange()) = 42; } // Test that device loss doesn't change the result of GetMappedRange, mappedAtCreation version. @@ -422,6 +425,9 @@ ASSERT_NE(buffer.GetMappedRange(), nullptr); ASSERT_EQ(buffer.GetMappedRange(), rangeBeforeLoss); + + // Write to the range as it should still point to valid memory. + *static_cast<uint32_t*>(buffer.GetMappedRange()) = 42; } // Test that device loss doesn't change the result of GetMappedRange, mapping for reading version. @@ -439,6 +445,14 @@ ASSERT_NE(buffer.GetConstMappedRange(), nullptr); ASSERT_EQ(buffer.GetConstMappedRange(), rangeBeforeLoss); + + if (!IsNull()) { + // Read from the range as it should still point to valid memory. Also check the value to + // force the compiler to keep the read. The null backend doesn't do zero init so we skip + // there. + uint32_t zero = *static_cast<const uint32_t*>(buffer.GetConstMappedRange()); + ASSERT_EQ(zero, 0u); + } } // Test that device loss doesn't change the result of GetMappedRange, mapping for writing version. @@ -456,6 +470,9 @@ ASSERT_NE(buffer.GetConstMappedRange(), nullptr); ASSERT_EQ(buffer.GetConstMappedRange(), rangeBeforeLoss); + + // Write to the range as it should still point to valid memory. + *static_cast<uint32_t*>(buffer.GetMappedRange()) = 42; } // TODO(dawn:929): mapasync read + resolve + loss getmappedrange != nullptr.
diff --git a/src/dawn/tests/unittests/validation/BufferValidationTests.cpp b/src/dawn/tests/unittests/validation/BufferValidationTests.cpp index 2fb47dc..716f0bf 100644 --- a/src/dawn/tests/unittests/validation/BufferValidationTests.cpp +++ b/src/dawn/tests/unittests/validation/BufferValidationTests.cpp
@@ -562,6 +562,42 @@ WaitForAllOperations(); } +// Test that destroying the device cancels the mapping operation. +TEST_P(BufferMappingValidationTest, DestroyDeviceWhilePending) { + wgpu::Buffer buffer = CreateBuffer(4); + + MockMapAsyncCallback mockCb; + EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Aborted, _)).Times(1); + buffer.MapAsync(GetParam(), 0, 4, wgpu::CallbackMode::AllowProcessEvents, mockCb.Callback()); + + ExpectDeviceDestruction(); + device.Destroy(); + + WaitForAllOperations(); + ASSERT_EQ(wgpu::BufferMapState::Unmapped, buffer.GetMapState()); +} + +// Test that destroying the device cancels the mapping operation. +TEST_P(BufferMappingValidationTest, DestroyDeviceAfterMapping) { + // TODO(https://crbug.com/42240407): Unmap buffers in the wire client when + // device.Destroy() is called. + DAWN_SKIP_TEST_IF(UsesWire()); + + wgpu::Buffer buffer = CreateBuffer(4); + + MockMapAsyncCallback mockCb; + EXPECT_CALL(mockCb, Call(wgpu::MapAsyncStatus::Success, _)).Times(1); + buffer.MapAsync(GetParam(), 0, 4, wgpu::CallbackMode::AllowProcessEvents, mockCb.Callback()); + WaitForAllOperations(); + + ASSERT_EQ(wgpu::BufferMapState::Mapped, buffer.GetMapState()); + + ExpectDeviceDestruction(); + device.Destroy(); + + ASSERT_EQ(wgpu::BufferMapState::Unmapped, buffer.GetMapState()); +} + // Test the success case for mappedAtCreation TEST_F(BufferValidationTest, MappedAtCreationSuccess) { BufferMappedAtCreation(4, wgpu::BufferUsage::MapWrite); @@ -596,6 +632,22 @@ } } +// Test that destroying the device cancels the mapping operation. +TEST_F(BufferValidationTest, MappedAtCreationThenDestroyDevice) { + // TODO(https://crbug.com/42240407): Unmap buffers in the wire client when + // device.Destroy() is called. + DAWN_SKIP_TEST_IF(UsesWire()); + + wgpu::Buffer buffer = BufferMappedAtCreation(4, wgpu::BufferUsage::CopySrc); + + ASSERT_EQ(wgpu::BufferMapState::Mapped, buffer.GetMapState()); + + ExpectDeviceDestruction(); + device.Destroy(); + + ASSERT_EQ(wgpu::BufferMapState::Unmapped, buffer.GetMapState()); +} + // Test that it is valid to destroy an error buffer TEST_F(BufferValidationTest, DestroyErrorBuffer) { wgpu::BufferDescriptor desc;
diff --git a/src/dawn/tests/unittests/validation/CommandBufferValidationTests.cpp b/src/dawn/tests/unittests/validation/CommandBufferValidationTests.cpp index 55244d5..b4bd8ff 100644 --- a/src/dawn/tests/unittests/validation/CommandBufferValidationTests.cpp +++ b/src/dawn/tests/unittests/validation/CommandBufferValidationTests.cpp
@@ -414,11 +414,10 @@ } } +// Test having the device destroyed before encoding. TEST_F(CommandBufferValidationTest, EncodeAfterDeviceDestroyed) { PlaceholderRenderPass placeholderRenderPass(device); - // Device destroyed before encoding. - { wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); ExpectDeviceDestruction(); device.Destroy(); @@ -427,19 +426,20 @@ wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&placeholderRenderPass); pass.End(); encoder.Finish(); - } +} - // Device destroyed after encoding. - { - ExpectDeviceDestruction(); - device.Destroy(); - wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); - // The encoder should not accessing any device info if device is destroyed when try - // encoding. - wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&placeholderRenderPass); - pass.End(); - encoder.Finish(); - } +// Test having the device destroyed after encoding but before Finish(). +TEST_F(CommandBufferValidationTest, FinishAfterDeviceDestroyed) { + PlaceholderRenderPass placeholderRenderPass(device); + + ExpectDeviceDestruction(); + device.Destroy(); + wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); + // The encoder should not accessing any device info if device is destroyed when try + // encoding. + wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&placeholderRenderPass); + pass.End(); + encoder.Finish(); } // Test that an error is produced when encoding happens after ending a pass.