[dawn][native] Move deprecation count for testing to instance.

- Test infrastructure can more easily validate deprecation warnings on
  all devices via the instance, especially when tests create multiple
  devices.

Change-Id: Ic5e8bf5d080a7ad605ece4611e6701b307240576
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/188082
Reviewed-by: Shrek Shao <shrekshao@google.com>
Commit-Queue: Loko Kung <lokokung@google.com>
Reviewed-by: Austin Eng <enga@chromium.org>
diff --git a/include/dawn/native/DawnNative.h b/include/dawn/native/DawnNative.h
index 4a0ec7d..2a44d87 100644
--- a/include/dawn/native/DawnNative.h
+++ b/include/dawn/native/DawnNative.h
@@ -180,6 +180,8 @@
     void EnableBeginCaptureOnStartup(bool beginCaptureOnStartup);
 
     uint64_t GetDeviceCountForTesting() const;
+    // Backdoor to get the number of deprecation warnings for testing
+    uint64_t GetDeprecationWarningCountForTesting() const;
 
     // Returns the underlying WGPUInstance object.
     WGPUInstance Get() const;
@@ -200,9 +202,6 @@
 // Backdoor to get the number of lazy clears for testing
 DAWN_NATIVE_EXPORT size_t GetLazyClearCountForTesting(WGPUDevice device);
 
-// Backdoor to get the number of deprecation warnings for testing
-DAWN_NATIVE_EXPORT size_t GetDeprecationWarningCountForTesting(WGPUDevice device);
-
 //  Query if texture has been initialized
 DAWN_NATIVE_EXPORT bool IsTextureSubresourceInitialized(
     WGPUTexture texture,
diff --git a/src/dawn/native/DawnNative.cpp b/src/dawn/native/DawnNative.cpp
index 9be48d5..cacb74c 100644
--- a/src/dawn/native/DawnNative.cpp
+++ b/src/dawn/native/DawnNative.cpp
@@ -212,6 +212,10 @@
     return mImpl->GetDeviceCountForTesting();
 }
 
+uint64_t Instance::GetDeprecationWarningCountForTesting() const {
+    return mImpl->GetDeprecationWarningCountForTesting();
+}
+
 WGPUInstance Instance::Get() const {
     return ToAPI(mImpl);
 }
@@ -224,10 +228,6 @@
     return FromAPI(device)->GetLazyClearCountForTesting();
 }
 
-size_t GetDeprecationWarningCountForTesting(WGPUDevice device) {
-    return FromAPI(device)->GetDeprecationWarningCountForTesting();
-}
-
 bool IsTextureSubresourceInitialized(WGPUTexture texture,
                                      uint32_t baseMipLevel,
                                      uint32_t levelCount,
diff --git a/src/dawn/native/Device.cpp b/src/dawn/native/Device.cpp
index e4bdc28..36c7717 100644
--- a/src/dawn/native/Device.cpp
+++ b/src/dawn/native/Device.cpp
@@ -128,11 +128,6 @@
     return ReturnType(result);
 }
 
-struct DeviceBase::DeprecationWarnings {
-    absl::flat_hash_set<std::string> emitted;
-    size_t count = 0;
-};
-
 namespace {
 
 struct LoggingCallbackTask : CallbackTask {
@@ -427,7 +422,6 @@
     mErrorScopeStack = std::make_unique<ErrorScopeStack>();
     mDynamicUploader = std::make_unique<DynamicUploader>(this);
     mCallbackTaskManager = AcquireRef(new CallbackTaskManager());
-    mDeprecationWarnings = std::make_unique<DeprecationWarnings>();
     mInternalPipelineStore = std::make_unique<InternalPipelineStore>(this);
 
     DAWN_ASSERT(GetPlatform() != nullptr);
@@ -792,7 +786,7 @@
 }
 
 void DeviceBase::APISetDeviceLostCallback(wgpu::DeviceLostCallback callback, void* userdata) {
-    EmitDeprecationWarning(
+    GetInstance()->EmitDeprecationWarning(
         "SetDeviceLostCallback is deprecated. Pass the callback in the device descriptor instead.");
 
     // The registered callback function and userdata pointer are stored and used by deferred
@@ -1804,17 +1798,6 @@
     ++mLazyClearCountForTesting;
 }
 
-size_t DeviceBase::GetDeprecationWarningCountForTesting() {
-    return mDeprecationWarnings->count;
-}
-
-void DeviceBase::EmitDeprecationWarning(const std::string& message) {
-    mDeprecationWarnings->count++;
-    if (mDeprecationWarnings->emitted.insert(message).second) {
-        dawn::WarningLog() << message;
-    }
-}
-
 void DeviceBase::EmitWarningOnce(const std::string& message) {
     if (mWarnings.insert(message).second) {
         this->EmitLog(WGPULoggingType_Warning, message.c_str());
@@ -2203,7 +2186,7 @@
 ResultOrError<Ref<SwapChainBase>> DeviceBase::CreateSwapChain(
     Surface* surface,
     const SwapChainDescriptor* descriptor) {
-    EmitDeprecationWarning(
+    GetInstance()->EmitDeprecationWarning(
         "The explicit creation of a SwapChain object is deprecated and should be replaced by "
         "Surface configuration.");
 
diff --git a/src/dawn/native/Device.h b/src/dawn/native/Device.h
index 831d0b8..360b1b5 100644
--- a/src/dawn/native/Device.h
+++ b/src/dawn/native/Device.h
@@ -357,8 +357,6 @@
 
     size_t GetLazyClearCountForTesting();
     void IncrementLazyClearCountForTesting();
-    size_t GetDeprecationWarningCountForTesting();
-    void EmitDeprecationWarning(const std::string& warning);
     void EmitWarningOnce(const std::string& message);
     void EmitLog(const char* message);
     void EmitLog(WGPULoggingType loggingType, const char* message);
@@ -572,8 +570,6 @@
     std::unique_ptr<DynamicUploader> mDynamicUploader;
     Ref<QueueBase> mQueue;
 
-    struct DeprecationWarnings;
-    std::unique_ptr<DeprecationWarnings> mDeprecationWarnings;
     std::atomic<uint32_t> mEmittedCompilationLogCount = 0;
 
     absl::flat_hash_set<std::string> mWarnings;
diff --git a/src/dawn/native/Instance.cpp b/src/dawn/native/Instance.cpp
index 29acf7d..177b084 100644
--- a/src/dawn/native/Instance.cpp
+++ b/src/dawn/native/Instance.cpp
@@ -135,6 +135,11 @@
 
 // InstanceBase
 
+struct InstanceBase::DeprecationWarnings {
+    absl::flat_hash_set<std::string> emitted;
+    uint64_t count = 0;
+};
+
 // static
 ResultOrError<Ref<InstanceBase>> InstanceBase::Create(const InstanceDescriptor* descriptor) {
     static constexpr InstanceDescriptor kDefaultDesc = {};
@@ -159,7 +164,8 @@
     return instance;
 }
 
-InstanceBase::InstanceBase(const TogglesState& instanceToggles) : mToggles(instanceToggles) {}
+InstanceBase::InstanceBase(const TogglesState& instanceToggles)
+    : mToggles(instanceToggles), mDeprecationWarnings(std::make_unique<DeprecationWarnings>()) {}
 
 InstanceBase::~InstanceBase() = default;
 
@@ -512,6 +518,17 @@
     return mPlatform;
 }
 
+uint64_t InstanceBase::GetDeprecationWarningCountForTesting() {
+    return mDeprecationWarnings->count;
+}
+
+void InstanceBase::EmitDeprecationWarning(const std::string& message) {
+    mDeprecationWarnings->count++;
+    if (mDeprecationWarnings->emitted.insert(message).second) {
+        dawn::WarningLog() << message;
+    }
+}
+
 uint64_t InstanceBase::GetDeviceCountForTesting() const {
     return mDevicesList.Use([](auto deviceList) { return deviceList->size(); });
 }
diff --git a/src/dawn/native/Instance.h b/src/dawn/native/Instance.h
index 1b4d894..942a8e3 100644
--- a/src/dawn/native/Instance.h
+++ b/src/dawn/native/Instance.h
@@ -126,6 +126,10 @@
     void SetPlatformForTesting(dawn::platform::Platform* platform);
     dawn::platform::Platform* GetPlatform();
 
+    // Testing only API that is NOT thread-safe.
+    uint64_t GetDeprecationWarningCountForTesting();
+    void EmitDeprecationWarning(const std::string& warning);
+
     uint64_t GetDeviceCountForTesting() const;
     void AddDevice(DeviceBase* device);
     void RemoveDevice(DeviceBase* device);
@@ -218,6 +222,9 @@
     Ref<CallbackTaskManager> mCallbackTaskManager;
     EventManager mEventManager;
 
+    struct DeprecationWarnings;
+    std::unique_ptr<DeprecationWarnings> mDeprecationWarnings;
+
     MutexProtected<absl::flat_hash_set<DeviceBase*>> mDevicesList;
 };
 
diff --git a/src/dawn/tests/DawnTest.cpp b/src/dawn/tests/DawnTest.cpp
index 0fbfa98..0fe90e6 100644
--- a/src/dawn/tests/DawnTest.cpp
+++ b/src/dawn/tests/DawnTest.cpp
@@ -719,6 +719,7 @@
 
 DawnTestBase::DawnTestBase(const AdapterTestParam& param) : mParam(param) {
     gCurrentTest = this;
+    mLastWarningCount = GetDeprecationWarningCountForTesting();
 
     DawnProcTable procs = native::GetProcs();
     // Override procs to provide harness-specific behavior to always select the adapter required in
@@ -1080,6 +1081,10 @@
     return true;
 }
 
+uint64_t DawnTestBase::GetDeprecationWarningCountForTesting() const {
+    return gTestEnv->GetInstance()->GetDeprecationWarningCountForTesting();
+}
+
 void* DawnTestBase::GetUniqueUserdata() {
     return reinterpret_cast<void*>(++mNextUniqueUserdata);
 }
@@ -1212,8 +1217,8 @@
 void DawnTestBase::TearDown() {
     ResolveDeferredExpectationsNow();
 
-    if (!UsesWire() && device) {
-        EXPECT_EQ(mLastWarningCount, native::GetDeprecationWarningCountForTesting(device.Get()));
+    if (!UsesWire()) {
+        EXPECT_EQ(mLastWarningCount, GetDeprecationWarningCountForTesting());
     }
 }
 
diff --git a/src/dawn/tests/DawnTest.h b/src/dawn/tests/DawnTest.h
index f99ac48..2d39371 100644
--- a/src/dawn/tests/DawnTest.h
+++ b/src/dawn/tests/DawnTest.h
@@ -331,7 +331,7 @@
     DawnProcTable backendProcs = {};
     WGPUDevice backendDevice = nullptr;
 
-    size_t mLastWarningCount = 0;
+    uint64_t mLastWarningCount = 0;
 
     // Mock callbacks tracking errors and destruction. These are strict mocks because any errors or
     // device loss that aren't expected should result in test failures and not just some warnings
@@ -607,6 +607,8 @@
     wgpu::SupportedLimits GetAdapterLimits();
     wgpu::SupportedLimits GetSupportedLimits();
 
+    uint64_t GetDeprecationWarningCountForTesting() const;
+
     void* GetUniqueUserdata();
 
   private:
@@ -713,20 +715,20 @@
 #define DAWN_SUPPRESS_TEST_IF(condition) \
     DAWN_SKIP_TEST_IF_BASE(!RunSuppressedTests() && condition, "suppressed", condition)
 
-#define EXPECT_DEPRECATION_WARNINGS(statement, n)                                               \
-    do {                                                                                        \
-        if (UsesWire()) {                                                                       \
-            statement;                                                                          \
-        } else {                                                                                \
-            size_t warningsBefore = native::GetDeprecationWarningCountForTesting(device.Get()); \
-            statement;                                                                          \
-            size_t warningsAfter = native::GetDeprecationWarningCountForTesting(device.Get());  \
-            EXPECT_EQ(mLastWarningCount, warningsBefore);                                       \
-            if (!HasToggleEnabled("skip_validation")) {                                         \
-                EXPECT_EQ(warningsAfter, warningsBefore + n);                                   \
-            }                                                                                   \
-            mLastWarningCount = warningsAfter;                                                  \
-        }                                                                                       \
+#define EXPECT_DEPRECATION_WARNINGS(statement, n)                             \
+    do {                                                                      \
+        if (UsesWire()) {                                                     \
+            statement;                                                        \
+        } else {                                                              \
+            uint64_t warningsBefore = GetDeprecationWarningCountForTesting(); \
+            statement;                                                        \
+            uint64_t warningsAfter = GetDeprecationWarningCountForTesting();  \
+            EXPECT_EQ(mLastWarningCount, warningsBefore);                     \
+            if (!HasToggleEnabled("skip_validation")) {                       \
+                EXPECT_EQ(warningsAfter, warningsBefore + n);                 \
+            }                                                                 \
+            mLastWarningCount = warningsAfter;                                \
+        }                                                                     \
     } while (0)
 #define EXPECT_DEPRECATION_WARNING(statement) EXPECT_DEPRECATION_WARNINGS(statement, 1)
 
diff --git a/src/dawn/tests/end2end/SwapChainTests.cpp b/src/dawn/tests/end2end/SwapChainTests.cpp
index 77bfe41..a7c21a2 100644
--- a/src/dawn/tests/end2end/SwapChainTests.cpp
+++ b/src/dawn/tests/end2end/SwapChainTests.cpp
@@ -264,7 +264,9 @@
             deviceToUse = device2;
         }
 
-        wgpu::SwapChain swapchain = deviceToUse.CreateSwapChain(surface, &baseDescriptor);
+        wgpu::SwapChain swapchain;
+        EXPECT_DEPRECATION_WARNING(swapchain =
+                                       deviceToUse.CreateSwapChain(surface, &baseDescriptor));
         swapchain.GetCurrentTexture();
         swapchain.Present();
     }
diff --git a/src/dawn/tests/unittests/validation/ValidationTest.cpp b/src/dawn/tests/unittests/validation/ValidationTest.cpp
index 21328b4..13ab01c 100644
--- a/src/dawn/tests/unittests/validation/ValidationTest.cpp
+++ b/src/dawn/tests/unittests/validation/ValidationTest.cpp
@@ -184,9 +184,10 @@
     FlushWire();
     ASSERT_FALSE(mExpectError);
 
-    if (device) {
-        EXPECT_EQ(mLastWarningCount,
-                  dawn::native::GetDeprecationWarningCountForTesting(backendDevice));
+    // Note that if the test is skipped before SetUp is called, mDawnInstance will not get set and
+    // remain nullptr.
+    if (mDawnInstance) {
+        EXPECT_EQ(mLastWarningCount, mDawnInstance->GetDeprecationWarningCountForTesting());
     }
 
     // The device will be destroyed soon after, so we want to set the expectation.
diff --git a/src/dawn/tests/unittests/validation/ValidationTest.h b/src/dawn/tests/unittests/validation/ValidationTest.h
index 6eb7d26..cd746e6 100644
--- a/src/dawn/tests/unittests/validation/ValidationTest.h
+++ b/src/dawn/tests/unittests/validation/ValidationTest.h
@@ -90,16 +90,16 @@
         }                                                       \
     } while (0)
 
-#define EXPECT_DEPRECATION_WARNINGS(statement, n)                                                  \
-    do {                                                                                           \
-        FlushWire();                                                                               \
-        size_t warningsBefore = dawn::native::GetDeprecationWarningCountForTesting(backendDevice); \
-        EXPECT_EQ(mLastWarningCount, warningsBefore);                                              \
-        statement;                                                                                 \
-        FlushWire();                                                                               \
-        size_t warningsAfter = dawn::native::GetDeprecationWarningCountForTesting(backendDevice);  \
-        EXPECT_EQ(warningsAfter, warningsBefore + n);                                              \
-        mLastWarningCount = warningsAfter;                                                         \
+#define EXPECT_DEPRECATION_WARNINGS(statement, n)                                        \
+    do {                                                                                 \
+        FlushWire();                                                                     \
+        uint64_t warningsBefore = mDawnInstance->GetDeprecationWarningCountForTesting(); \
+        EXPECT_EQ(mLastWarningCount, warningsBefore);                                    \
+        statement;                                                                       \
+        FlushWire();                                                                     \
+        uint64_t warningsAfter = mDawnInstance->GetDeprecationWarningCountForTesting();  \
+        EXPECT_EQ(warningsAfter, warningsBefore + n);                                    \
+        mLastWarningCount = warningsAfter;                                               \
     } while (0)
 #define EXPECT_DEPRECATION_WARNING(statement) EXPECT_DEPRECATION_WARNINGS(statement, 1)
 
@@ -191,7 +191,7 @@
     WGPUDevice backendDevice;
     wgpu::Instance instance;
 
-    size_t mLastWarningCount = 0;
+    uint64_t mLastWarningCount = 0;
 
   private:
     std::unique_ptr<dawn::native::Instance> mDawnInstance;