Handle Device Lost for SwapChain

Bug: dawn:68
Change-Id: I16e00bb2e203e71fd0840b71bc027e6fbea4e52c
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/15723
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Natasha Lee <natlee@microsoft.com>
diff --git a/src/dawn_native/SwapChain.cpp b/src/dawn_native/SwapChain.cpp
index 1053aaf..547bd62 100644
--- a/src/dawn_native/SwapChain.cpp
+++ b/src/dawn_native/SwapChain.cpp
@@ -220,6 +220,7 @@
                                                    wgpu::TextureUsage allowedUsage,
                                                    uint32_t width,
                                                    uint32_t height) const {
+        DAWN_TRY(GetDevice()->ValidateIsAlive());
         DAWN_TRY(GetDevice()->ValidateObject(this));
 
         DAWN_TRY(ValidateTextureUsage(allowedUsage));
@@ -233,6 +234,7 @@
     }
 
     MaybeError OldSwapChainBase::ValidateGetCurrentTextureView() const {
+        DAWN_TRY(GetDevice()->ValidateIsAlive());
         DAWN_TRY(GetDevice()->ValidateObject(this));
 
         if (mWidth == 0) {
@@ -244,6 +246,7 @@
     }
 
     MaybeError OldSwapChainBase::ValidatePresent() const {
+        DAWN_TRY(GetDevice()->ValidateIsAlive());
         DAWN_TRY(GetDevice()->ValidateObject(this));
 
         if (mCurrentTextureView.Get() == nullptr) {
diff --git a/src/dawn_native/Texture.cpp b/src/dawn_native/Texture.cpp
index 5ec3b1f2..7b264c1 100644
--- a/src/dawn_native/Texture.cpp
+++ b/src/dawn_native/Texture.cpp
@@ -503,7 +503,6 @@
     }
 
     MaybeError TextureBase::ValidateDestroy() const {
-        DAWN_TRY(GetDevice()->ValidateIsAlive());
         DAWN_TRY(GetDevice()->ValidateObject(this));
         return {};
     }
diff --git a/src/tests/end2end/SwapChainValidationTests.cpp b/src/tests/end2end/SwapChainValidationTests.cpp
index 1900604..daa7108 100644
--- a/src/tests/end2end/SwapChainValidationTests.cpp
+++ b/src/tests/end2end/SwapChainValidationTests.cpp
@@ -290,3 +290,36 @@
     CheckTextureViewIsDestroyed(view);
     ASSERT_DEVICE_ERROR(replacedSwapChain.Present());
 }
+
+// Test that after Device is Lost, all swap chain operations fail
+static void ToMockDeviceLostCallback(const char* message, void* userdata) {
+    ValidationTest* self = static_cast<ValidationTest*>(userdata);
+    self->StartExpectDeviceError();
+}
+
+// Test that new swap chain present fails after device is lost
+TEST_F(SwapChainValidationTests, NewSwapChainPresentFailsAfterDeviceLost) {
+    device.SetDeviceLostCallback(ToMockDeviceLostCallback, this);
+    wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &goodDescriptor);
+    wgpu::TextureView view = swapchain.GetCurrentTextureView();
+
+    device.LoseForTesting();
+    ASSERT_DEVICE_ERROR(swapchain.Present());
+}
+
+// Test that new swap chain get current texture view fails after device is lost
+TEST_F(SwapChainValidationTests, NewSwapChainGetCurrentTextureViewFailsAfterDevLost) {
+    device.SetDeviceLostCallback(ToMockDeviceLostCallback, this);
+    wgpu::SwapChain swapchain = device.CreateSwapChain(surface, &goodDescriptor);
+
+    device.LoseForTesting();
+    ASSERT_DEVICE_ERROR(swapchain.GetCurrentTextureView());
+}
+
+// Test that creation of a new swapchain fails
+TEST_F(SwapChainValidationTests, CreateNewSwapChainFailsAfterDevLost) {
+    device.SetDeviceLostCallback(ToMockDeviceLostCallback, this);
+    device.LoseForTesting();
+
+    ASSERT_DEVICE_ERROR(device.CreateSwapChain(surface, &goodDescriptor));
+}