d3d12: Retry root signature serialization with 1.0 if version 1.1 failed

Some drivers do not correctly report what they support, so we need to
try again with version 1.0

Bug: chromium:1512318
Change-Id: Iaf7a38e33cbd95d4442af695eecf79dbb7245469
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/166641
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
Commit-Queue: Antonio Maiorano <amaiorano@google.com>
Auto-Submit: Austin Eng <enga@chromium.org>
diff --git a/src/dawn/native/d3d12/PipelineLayoutD3D12.cpp b/src/dawn/native/d3d12/PipelineLayoutD3D12.cpp
index 28964bd..c56e294 100644
--- a/src/dawn/native/d3d12/PipelineLayoutD3D12.cpp
+++ b/src/dawn/native/d3d12/PipelineLayoutD3D12.cpp
@@ -339,27 +339,36 @@
     versionedRootSignatureDescriptor.Desc_1_1.Flags =
         D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
 
-    ComPtr<ID3DBlob> error;
-    HRESULT hr;
-    if (device->IsToggleEnabled(Toggle::D3D12UseRootSignatureVersion1_1)) {
-        hr = device->GetFunctions()->d3d12SerializeVersionedRootSignature(
-            &versionedRootSignatureDescriptor, &mRootSignatureBlob, &error);
-    } else {
-        hr = SerializeRootParameter1_0(device, versionedRootSignatureDescriptor,
-                                       &mRootSignatureBlob, &error);
-    }
-    if (DAWN_UNLIKELY(FAILED(hr))) {
+    DAWN_TRY([&]() -> MaybeError {
+        ComPtr<ID3DBlob> error;
+        if (device->IsToggleEnabled(Toggle::D3D12UseRootSignatureVersion1_1) &&
+            DAWN_LIKELY(SUCCEEDED(device->GetFunctions()->d3d12SerializeVersionedRootSignature(
+                &versionedRootSignatureDescriptor, &mRootSignatureBlob, &error)))) {
+            return {};
+        }
+        // If using root signature version 1.1 failed, try again with root signature version 1.0.
+        // Some drivers appear to run an outdated version of the DXIL validator and can't support
+        // 1.1.
+        // Note that retrying again is OK because whether we use version 1.0 or 1.1 doesn't
+        // affect anything else except pipeline layout creation. Nothing else in Dawn cares
+        // what decision we made here.
+        // TODO(crbug.com/1512318): Add some telemetry so we log how often/when this happens.
         std::ostringstream messageStream;
         if (error) {
-            messageStream << static_cast<const char*>(error->GetBufferPointer());
-
-            // |error| is observed to always end with a \n, but is not
-            // specified to do so, so we add an extra newline just in case.
-            messageStream << std::endl;
+            messageStream << static_cast<const char*>(error->GetBufferPointer()) << std::endl;
+        }
+        HRESULT hr = SerializeRootParameter1_0(device, versionedRootSignatureDescriptor,
+                                               &mRootSignatureBlob, &error);
+        if (DAWN_LIKELY(SUCCEEDED(hr))) {
+            return {};
+        }
+        if (error) {
+            messageStream << static_cast<const char*>(error->GetBufferPointer()) << std::endl;
         }
         messageStream << "D3D12 serialize root signature";
         DAWN_TRY(CheckHRESULT(hr, messageStream.str().c_str()));
-    }
+        return {};
+    }());
     DAWN_TRY(CheckHRESULT(device->GetD3D12Device()->CreateRootSignature(
                               0, mRootSignatureBlob->GetBufferPointer(),
                               mRootSignatureBlob->GetBufferSize(), IID_PPV_ARGS(&mRootSignature)),