Support FL 11.0 adapters if they have at least Resource Binding Tier 2

Bug: dawn:1185
Change-Id: I8f7798def463c9e2a18e1f855908afe05bae8e04
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/68780
Commit-Queue: Austin Eng <enga@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn_native/d3d12/AdapterD3D12.cpp b/src/dawn_native/d3d12/AdapterD3D12.cpp
index 99e4603..d1baba3 100644
--- a/src/dawn_native/d3d12/AdapterD3D12.cpp
+++ b/src/dawn_native/d3d12/AdapterD3D12.cpp
@@ -66,7 +66,7 @@
         // Create the device to populate the adapter properties then reuse it when needed for actual
         // rendering.
         const PlatformFunctions* functions = GetBackend()->GetFunctions();
-        if (FAILED(functions->d3d12CreateDevice(GetHardwareAdapter(), D3D_FEATURE_LEVEL_11_1,
+        if (FAILED(functions->d3d12CreateDevice(GetHardwareAdapter(), D3D_FEATURE_LEVEL_11_0,
                                                 _uuidof(ID3D12Device), &mD3d12Device))) {
             return DAWN_INTERNAL_ERROR("D3D12CreateDevice failed");
         }
@@ -143,7 +143,25 @@
 
         DAWN_TRY(CheckHRESULT(mD3d12Device->CheckFeatureSupport(D3D12_FEATURE_D3D12_OPTIONS,
                                                                 &featureData, sizeof(featureData)),
-                              "CheckFeatureSupport"));
+                              "CheckFeatureSupport D3D12_FEATURE_D3D12_OPTIONS"));
+
+        // Check if the device is at least D3D_FEATURE_LEVEL_11_1 or D3D_FEATURE_LEVEL_11_0
+        const D3D_FEATURE_LEVEL levelsToQuery[]{D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_11_0};
+
+        D3D12_FEATURE_DATA_FEATURE_LEVELS featureLevels;
+        featureLevels.NumFeatureLevels = sizeof(levelsToQuery) / sizeof(D3D_FEATURE_LEVEL);
+        featureLevels.pFeatureLevelsRequested = levelsToQuery;
+        DAWN_TRY(
+            CheckHRESULT(mD3d12Device->CheckFeatureSupport(D3D12_FEATURE_FEATURE_LEVELS,
+                                                           &featureLevels, sizeof(featureLevels)),
+                         "CheckFeatureSupport D3D12_FEATURE_FEATURE_LEVELS"));
+
+        if (featureLevels.MaxSupportedFeatureLevel == D3D_FEATURE_LEVEL_11_0 &&
+            featureData.ResourceBindingTier < D3D12_RESOURCE_BINDING_TIER_2) {
+            return DAWN_VALIDATION_ERROR(
+                "At least Resource Binding Tier 2 is required for D3D12 Feature Level 11.0 "
+                "devices.");
+        }
 
         GetDefaultLimits(&limits->v1);
 
@@ -190,22 +208,22 @@
                 maxSamplersPerStage = 2048;
                 break;
             case D3D12_RESOURCE_BINDING_TIER_3:
+            default:
                 maxCBVsPerStage = 1'100'000;
                 maxSRVsPerStage = 1'100'000;
                 maxUAVsAllStages = 1'100'000;
                 maxSamplersPerStage = 2048;
                 break;
-            default:
-                UNREACHABLE();
         }
 
-        ASSERT(maxUAVsAllStages / 2 > limits->v1.maxStorageTexturesPerShaderStage);
-        ASSERT(maxUAVsAllStages / 2 > limits->v1.maxStorageBuffersPerShaderStage);
+        ASSERT(maxUAVsAllStages / 4 > limits->v1.maxStorageTexturesPerShaderStage);
+        ASSERT(maxUAVsAllStages / 4 > limits->v1.maxStorageBuffersPerShaderStage);
+        uint32_t maxUAVsPerStage = maxUAVsAllStages / 2;
 
         limits->v1.maxUniformBuffersPerShaderStage = maxCBVsPerStage;
         // Allocate half of the UAVs to storage buffers, and half to storage textures.
-        limits->v1.maxStorageTexturesPerShaderStage = maxUAVsAllStages / 2;
-        limits->v1.maxStorageBuffersPerShaderStage = maxUAVsAllStages - maxUAVsAllStages / 2;
+        limits->v1.maxStorageTexturesPerShaderStage = maxUAVsPerStage / 2;
+        limits->v1.maxStorageBuffersPerShaderStage = maxUAVsPerStage - maxUAVsPerStage / 2;
         limits->v1.maxSampledTexturesPerShaderStage = maxSRVsPerStage;
         limits->v1.maxSamplersPerShaderStage = maxSamplersPerStage;