Allow externally enabled debug layer work without crash

Dawn relies on debug layer info queue filters to remove ignorable
messages of various ids and severity levels. Unfortunately, these
filters get ignored when the debug layer is enabled externally via
dxcpl.exe or d3dconfig.exe.

Since multiple systems in Chromium such as Media, WebNN and ANGLE
use D3D at the same time as Dawn, it's nice to enable the debug layer
for everything at once instead of doing it piecemeal for each system.

Dawn needs to be more robust in these instances by self-filtering
messages.

Bug: 348598130
Change-Id: I50bbfe3f99ba052d3a86137936b3be5b536e7c45
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/195254
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Rafael Cintron <rafael.cintron@microsoft.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn/native/d3d11/DeviceD3D11.cpp b/src/dawn/native/d3d11/DeviceD3D11.cpp
index 757fad9..4fddf0b 100644
--- a/src/dawn/native/d3d11/DeviceD3D11.cpp
+++ b/src/dawn/native/d3d11/DeviceD3D11.cpp
@@ -67,14 +67,35 @@
 
 static constexpr uint64_t kMaxDebugMessagesToPrint = 5;
 
-void AppendDebugLayerMessagesToError(ID3D11InfoQueue* infoQueue,
-                                     uint64_t totalErrors,
-                                     ErrorData* error) {
+bool SkipDebugMessage(const D3D11_MESSAGE& message) {
+    // Filter out messages that are not warnings or errors.
+    switch (message.Severity) {
+        case D3D11_MESSAGE_SEVERITY_INFO:
+        case D3D11_MESSAGE_SEVERITY_MESSAGE:
+            return true;
+        default:
+            break;
+    }
+
+    switch (message.ID) {
+        // D3D11 Debug layer warns no RTV set, however it is allowed.
+        case D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET:
+        // D3D11 Debug layer warns SetPrivateData() with same name more than once.
+        case D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS:
+            return true;
+        default:
+            return false;
+    }
+}
+
+uint64_t AppendDebugLayerMessagesToError(ID3D11InfoQueue* infoQueue,
+                                         uint64_t totalErrors,
+                                         ErrorData* error) {
     DAWN_ASSERT(totalErrors > 0);
     DAWN_ASSERT(error != nullptr);
 
-    uint64_t errorsToPrint = std::min(kMaxDebugMessagesToPrint, totalErrors);
-    for (uint64_t i = 0; i < errorsToPrint; ++i) {
+    uint64_t errorsEmitted = 0;
+    for (uint64_t i = 0; i < totalErrors; ++i) {
         std::ostringstream messageStream;
         SIZE_T messageLength = 0;
         HRESULT hr = infoQueue->GetMessage(i, nullptr, &messageLength);
@@ -93,17 +114,29 @@
             continue;
         }
 
+        if (SkipDebugMessage(*message)) {
+            continue;
+        }
+
         messageStream << "(" << message->ID << ") " << message->pDescription;
         error->AppendBackendMessage(messageStream.str());
+
+        errorsEmitted++;
+        if (errorsEmitted >= kMaxDebugMessagesToPrint) {
+            break;
+        }
     }
-    if (errorsToPrint < totalErrors) {
+
+    if (errorsEmitted < totalErrors) {
         std::ostringstream messages;
-        messages << (totalErrors - errorsToPrint) << " messages silenced";
+        messages << (totalErrors - errorsEmitted) << " messages silenced";
         error->AppendBackendMessage(messages.str());
     }
 
     // We only print up to the first kMaxDebugMessagesToPrint errors
     infoQueue->ClearStoredMessages();
+
+    return errorsEmitted;
 }
 
 }  // namespace
@@ -326,18 +359,21 @@
     ComPtr<ID3D11InfoQueue> infoQueue;
     DAWN_TRY(CheckHRESULT(mD3d11Device.As(&infoQueue),
                           "D3D11 QueryInterface ID3D11Device to ID3D11InfoQueue"));
-    uint64_t totalErrors = infoQueue->GetNumStoredMessagesAllowedByRetrievalFilter();
 
-    // Check if any errors have occurred otherwise we would be creating an empty error. Note
-    // that we use GetNumStoredMessagesAllowedByRetrievalFilter instead of GetNumStoredMessages
-    // because we only convert WARNINGS or higher messages to dawn errors.
+    // We use GetNumStoredMessages instead of applying a retrieval filter because dxcpl.exe
+    // and d3dconfig.exe override any filter settings we apply.
+    const uint64_t totalErrors = infoQueue->GetNumStoredMessages();
     if (totalErrors == 0) {
         return {};
     }
 
     auto error = DAWN_INTERNAL_ERROR("The D3D11 debug layer reported uncaught errors.");
 
-    AppendDebugLayerMessagesToError(infoQueue.Get(), totalErrors, error.get());
+    const uint64_t emittedErrors =
+        AppendDebugLayerMessagesToError(infoQueue.Get(), totalErrors, error.get());
+    if (emittedErrors == 0) {
+        return {};
+    }
 
     return error;
 }
@@ -351,8 +387,8 @@
     if (FAILED(mD3d11Device.As(&infoQueue))) {
         return;
     }
-    uint64_t totalErrors = infoQueue->GetNumStoredMessagesAllowedByRetrievalFilter();
 
+    const uint64_t totalErrors = infoQueue->GetNumStoredMessages();
     if (totalErrors == 0) {
         return;
     }
diff --git a/src/dawn/native/d3d11/PhysicalDeviceD3D11.cpp b/src/dawn/native/d3d11/PhysicalDeviceD3D11.cpp
index 4da0c91..ffc1f5d 100644
--- a/src/dawn/native/d3d11/PhysicalDeviceD3D11.cpp
+++ b/src/dawn/native/d3d11/PhysicalDeviceD3D11.cpp
@@ -41,43 +41,6 @@
 #include "dawn/native/d3d11/UtilsD3D11.h"
 
 namespace dawn::native::d3d11 {
-namespace {
-
-MaybeError InitializeDebugLayerFilters(ComPtr<ID3D11Device> d3d11Device) {
-    ComPtr<ID3D11InfoQueue> infoQueue;
-    DAWN_TRY(CheckHRESULT(d3d11Device.As(&infoQueue),
-                          "D3D11 querying device for ID3D11InfoQueue interface"));
-
-    static D3D11_MESSAGE_ID kDenyIds[] = {
-        // D3D11 Debug layer warns no RTV set, however it is allowed.
-        D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET,
-        // D3D11 Debug layer warns SetPrivateData() with same name more than once.
-        D3D11_MESSAGE_ID_SETPRIVATEDATA_CHANGINGPARAMS,
-    };
-
-    // Filter out info/message and only create errors from warnings or worse.
-    static D3D11_MESSAGE_SEVERITY kDenySeverities[] = {
-        D3D11_MESSAGE_SEVERITY_INFO,
-        D3D11_MESSAGE_SEVERITY_MESSAGE,
-    };
-
-    static D3D11_INFO_QUEUE_FILTER filter = {
-        {},  // AllowList
-        {
-            0,                           // NumCategories
-            nullptr,                     // pCategoryList
-            std::size(kDenySeverities),  // NumSeverities
-            kDenySeverities,             // pSeverityList
-            std::size(kDenyIds),         // NumIDs
-            kDenyIds,                    // pIDList
-        },                               // DenyList
-    };
-
-    return CheckHRESULT(infoQueue->PushStorageFilter(&filter),
-                        "D3D11 InfoQueue pushing storage filter");
-}
-
-}  // namespace
 
 PhysicalDevice::PhysicalDevice(Backend* backend,
                                ComPtr<IDXGIAdapter4> hardwareAdapter,
@@ -111,11 +74,6 @@
 ResultOrError<ComPtr<ID3D11Device>> PhysicalDevice::CreateD3D11Device(bool enableDebugLayer) {
     if (mIsSharedD3D11Device) {
         DAWN_ASSERT(mD3D11Device);
-        // If the shared d3d11 device was created with debug layer, we have to initialize debug
-        // layer filters to avoid some unwanted warnings.
-        if (IsDebugLayerEnabled(mD3D11Device)) {
-            DAWN_TRY(InitializeDebugLayerFilters(mD3D11Device));
-        }
         return ComPtr<ID3D11Device>(mD3D11Device);
     }
 
@@ -143,7 +101,6 @@
 
         if (SUCCEEDED(hr)) {
             DAWN_ASSERT(IsDebugLayerEnabled(d3d11Device));
-            DAWN_TRY(InitializeDebugLayerFilters(d3d11Device));
             return d3d11Device;
         }
     }