Fail any ANGLE test if it outputs D3D11 SDK message in debug mode

Also:
 - Disable some Feature Level 9_3 tests that trigger SDK messages
 - Fix a debug object name issue. If you try to assign a debug name
   to an object twice then you get an SDK warning message. This can
   occur if you 'create' two objects (e.g. Rasterizer States) with
   identical DESCs on the same device, since D3D11 can optimize
   this and return the same object both times.
 - Disable the message checks in Line Loops tests, since the tests
   trigger incorrect D3D11 SDK messages on Win7 machines

BUG=angleproject:667;angleproject:1282

Change-Id: I7284fb3a11377afde24e0014e21dbcea80ebb126
Reviewed-on: https://chromium-review.googlesource.com/321393
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Tryjob-Request: Austin Kinross <aukinros@microsoft.com>
Tested-by: Austin Kinross <aukinros@microsoft.com>
diff --git a/src/tests/test_utils/ANGLETest.cpp b/src/tests/test_utils/ANGLETest.cpp
index 780f57a..aebe28c 100644
--- a/src/tests/test_utils/ANGLETest.cpp
+++ b/src/tests/test_utils/ANGLETest.cpp
@@ -13,9 +13,7 @@
 #include "system_utils.h"
 
 ANGLETest::ANGLETest()
-    : mEGLWindow(nullptr),
-      mWidth(16),
-      mHeight(16)
+    : mEGLWindow(nullptr), mWidth(16), mHeight(16), mIgnoreD3D11SDKLayersWarnings(false)
 {
     mEGLWindow =
         new EGLWindow(GetParam().majorVersion, GetParam().minorVersion, GetParam().eglParameters);
@@ -64,6 +62,8 @@
 
 void ANGLETest::TearDown()
 {
+    checkD3D11SDKLayersMessages();
+
     const auto &info = testing::UnitTest::GetInstance()->current_test_info();
     angle::WriteDebugMessage("Exiting %s.%s\n", info->test_case_name(), info->name());
 
@@ -166,6 +166,79 @@
     return shader;
 }
 
+void ANGLETest::checkD3D11SDKLayersMessages()
+{
+#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(NDEBUG)
+    // In debug D3D11 mode, check ID3D11InfoQueue to see if any D3D11 SDK Layers messages
+    // were outputted by the test
+    if (mIgnoreD3D11SDKLayersWarnings ||
+        mEGLWindow->getPlatform().renderer != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE ||
+        mEGLWindow->getDisplay() == EGL_NO_DISPLAY)
+    {
+        return;
+    }
+
+    const char *extensionString =
+        static_cast<const char *>(eglQueryString(mEGLWindow->getDisplay(), EGL_EXTENSIONS));
+    if (!strstr(extensionString, "EGL_EXT_device_query"))
+    {
+        return;
+    }
+
+    EGLAttrib device      = 0;
+    EGLAttrib angleDevice = 0;
+
+    PFNEGLQUERYDISPLAYATTRIBEXTPROC queryDisplayAttribEXT;
+    PFNEGLQUERYDEVICEATTRIBEXTPROC queryDeviceAttribEXT;
+
+    queryDisplayAttribEXT = reinterpret_cast<PFNEGLQUERYDISPLAYATTRIBEXTPROC>(
+        eglGetProcAddress("eglQueryDisplayAttribEXT"));
+    queryDeviceAttribEXT = reinterpret_cast<PFNEGLQUERYDEVICEATTRIBEXTPROC>(
+        eglGetProcAddress("eglQueryDeviceAttribEXT"));
+    ASSERT_NE(nullptr, queryDisplayAttribEXT);
+    ASSERT_NE(nullptr, queryDeviceAttribEXT);
+
+    ASSERT_EGL_TRUE(queryDisplayAttribEXT(mEGLWindow->getDisplay(), EGL_DEVICE_EXT, &angleDevice));
+    ASSERT_EGL_TRUE(queryDeviceAttribEXT(reinterpret_cast<EGLDeviceEXT>(angleDevice),
+                                         EGL_D3D11_DEVICE_ANGLE, &device));
+    ID3D11Device *d3d11Device = reinterpret_cast<ID3D11Device *>(device);
+
+    ID3D11InfoQueue *infoQueue = nullptr;
+    HRESULT hr =
+        d3d11Device->QueryInterface(__uuidof(infoQueue), reinterpret_cast<void **>(&infoQueue));
+    if (SUCCEEDED(hr))
+    {
+        UINT64 numStoredD3DDebugMessages =
+            infoQueue->GetNumStoredMessagesAllowedByRetrievalFilter();
+
+        if (numStoredD3DDebugMessages > 0)
+        {
+            for (UINT64 i = 0; i < numStoredD3DDebugMessages; i++)
+            {
+                SIZE_T messageLength = 0;
+                hr                   = infoQueue->GetMessage(i, nullptr, &messageLength);
+
+                if (SUCCEEDED(hr))
+                {
+                    D3D11_MESSAGE *pMessage =
+                        reinterpret_cast<D3D11_MESSAGE *>(malloc(messageLength));
+                    infoQueue->GetMessage(i, pMessage, &messageLength);
+
+                    std::cout << "Message " << i << ":"
+                              << " " << pMessage->pDescription << "\n";
+                    free(pMessage);
+                }
+            }
+
+            FAIL() << numStoredD3DDebugMessages
+                   << " D3D11 SDK Layers message(s) detected! Test Failed.\n";
+        }
+    }
+
+    SafeRelease(infoQueue);
+#endif
+}
+
 static bool checkExtensionExists(const char *allExtensions, const std::string &extName)
 {
     return strstr(allExtensions, extName.c_str()) != nullptr;
@@ -352,6 +425,12 @@
     return mEGLWindow->getPlatform().renderer;
 }
 
+void ANGLETest::ignoreD3D11SDKLayersWarnings()
+{
+    // Some tests may need to disable the D3D11 SDK Layers Warnings checks
+    mIgnoreD3D11SDKLayersWarnings = true;
+}
+
 OSWindow *ANGLETest::mOSWindow = NULL;
 
 void ANGLETestEnvironment::SetUp()