Compat: Reject Bgra8Unorm-Srgb textures and views

Bug: dawn:1871
Change-Id: I418a8c0f59abb5fae27098c00d5179a5dd184144
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/137202
Reviewed-by: Austin Eng <enga@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Gregg Tavares <gman@chromium.org>
Reviewed-by: Stephen White <senorblanco@chromium.org>
diff --git a/src/dawn/native/Device.cpp b/src/dawn/native/Device.cpp
index 0b65bd1..9fde3ee 100644
--- a/src/dawn/native/Device.cpp
+++ b/src/dawn/native/Device.cpp
@@ -796,7 +796,8 @@
     DAWN_INVALID_IF(index >= mFormatTable.size(), "Unknown texture format %s.", format);
 
     const Format* internalFormat = &mFormatTable[index];
-    DAWN_INVALID_IF(!internalFormat->isSupported, "Unsupported texture format %s.", format);
+    DAWN_INVALID_IF(!internalFormat->IsSupported(), "Unsupported texture format %s, reason: %s.",
+                    format, internalFormat->unsupportedReason);
 
     return internalFormat;
 }
@@ -804,13 +805,13 @@
 const Format& DeviceBase::GetValidInternalFormat(wgpu::TextureFormat format) const {
     FormatIndex index = ComputeFormatIndex(format);
     ASSERT(index < mFormatTable.size());
-    ASSERT(mFormatTable[index].isSupported);
+    ASSERT(mFormatTable[index].IsSupported());
     return mFormatTable[index];
 }
 
 const Format& DeviceBase::GetValidInternalFormat(FormatIndex index) const {
     ASSERT(index < mFormatTable.size());
-    ASSERT(mFormatTable[index].isSupported);
+    ASSERT(mFormatTable[index].IsSupported());
     return mFormatTable[index];
 }
 
diff --git a/src/dawn/native/Format.cpp b/src/dawn/native/Format.cpp
index 23f17ca..17298fa 100644
--- a/src/dawn/native/Format.cpp
+++ b/src/dawn/native/Format.cpp
@@ -64,6 +64,12 @@
     return static_cast<SampleTypeBit>(1 << (static_cast<uint32_t>(sampleType) - 1));
 }
 
+const UnsupportedReason Format::supported;
+
+bool Format::IsSupported() const {
+    return std::holds_alternative<std::monostate>(unsupportedReason);
+}
+
 bool Format::IsColor() const {
     return aspects == Aspect::Color;
 }
@@ -161,18 +167,18 @@
         formatsSet.set(index);
     };
 
-    auto AddColorFormat =
-        [&AddFormat](wgpu::TextureFormat format, bool renderable, bool supportsStorageUsage,
-                     bool supportsMultisample, bool supportsResolveTarget, uint32_t byteSize,
-                     SampleTypeBit sampleTypes, uint8_t componentCount,
-                     uint8_t renderTargetPixelByteCost = 0,
+    auto AddConditionalColorFormat =
+        [&AddFormat](wgpu::TextureFormat format, UnsupportedReason unsupportedReason,
+                     bool renderable, bool supportsStorageUsage, bool supportsMultisample,
+                     bool supportsResolveTarget, uint32_t byteSize, SampleTypeBit sampleTypes,
+                     uint8_t componentCount, uint8_t renderTargetPixelByteCost = 0,
                      uint8_t renderTargetComponentAlignment = 0,
                      wgpu::TextureFormat baseFormat = wgpu::TextureFormat::Undefined) {
             Format internalFormat;
             internalFormat.format = format;
             internalFormat.isRenderable = renderable;
             internalFormat.isCompressed = false;
-            internalFormat.isSupported = true;
+            internalFormat.unsupportedReason = unsupportedReason;
             internalFormat.supportsStorageUsage = supportsStorageUsage;
 
             if (supportsMultisample) {
@@ -225,14 +231,27 @@
             AddFormat(internalFormat);
         };
 
+    auto AddColorFormat =
+        [&AddConditionalColorFormat](
+            wgpu::TextureFormat format, bool renderable, bool supportsStorageUsage,
+            bool supportsMultisample, bool supportsResolveTarget, uint32_t byteSize,
+            SampleTypeBit sampleTypes, uint8_t componentCount,
+            uint8_t renderTargetPixelByteCost = 0, uint8_t renderTargetComponentAlignment = 0,
+            wgpu::TextureFormat baseFormat = wgpu::TextureFormat::Undefined) {
+            AddConditionalColorFormat(format, std::monostate{}, renderable, supportsStorageUsage,
+                                      supportsMultisample, supportsResolveTarget, byteSize,
+                                      sampleTypes, componentCount, renderTargetPixelByteCost,
+                                      renderTargetComponentAlignment, baseFormat);
+        };
+
     auto AddDepthFormat = [&AddFormat](wgpu::TextureFormat format, uint32_t byteSize,
-                                       bool isSupported) {
+                                       UnsupportedReason unsupportedReason) {
         Format internalFormat;
         internalFormat.format = format;
         internalFormat.baseFormat = format;
         internalFormat.isRenderable = true;
         internalFormat.isCompressed = false;
-        internalFormat.isSupported = isSupported;
+        internalFormat.unsupportedReason = unsupportedReason;
         internalFormat.supportsStorageUsage = false;
         internalFormat.supportsMultisample = true;
         internalFormat.supportsResolveTarget = false;
@@ -249,13 +268,14 @@
         AddFormat(internalFormat);
     };
 
-    auto AddStencilFormat = [&AddFormat](wgpu::TextureFormat format, bool isSupported) {
+    auto AddStencilFormat = [&AddFormat](wgpu::TextureFormat format,
+                                         UnsupportedReason unsupportedReason) {
         Format internalFormat;
         internalFormat.format = format;
         internalFormat.baseFormat = format;
         internalFormat.isRenderable = true;
         internalFormat.isCompressed = false;
-        internalFormat.isSupported = isSupported;
+        internalFormat.unsupportedReason = unsupportedReason;
         internalFormat.supportsStorageUsage = false;
         internalFormat.supportsMultisample = true;
         internalFormat.supportsResolveTarget = false;
@@ -283,13 +303,13 @@
 
     auto AddCompressedFormat =
         [&AddFormat](wgpu::TextureFormat format, uint32_t byteSize, uint32_t width, uint32_t height,
-                     bool isSupported, uint8_t componentCount,
+                     UnsupportedReason unsupportedReason, uint8_t componentCount,
                      wgpu::TextureFormat baseFormat = wgpu::TextureFormat::Undefined) {
             Format internalFormat;
             internalFormat.format = format;
             internalFormat.isRenderable = false;
             internalFormat.isCompressed = true;
-            internalFormat.isSupported = isSupported;
+            internalFormat.unsupportedReason = unsupportedReason;
             internalFormat.supportsStorageUsage = false;
             internalFormat.supportsMultisample = false;
             internalFormat.supportsResolveTarget = false;
@@ -316,14 +336,14 @@
     auto AddMultiAspectFormat =
         [&AddFormat, &table](wgpu::TextureFormat format, Aspect aspects,
                              wgpu::TextureFormat firstFormat, wgpu::TextureFormat secondFormat,
-                             bool isRenderable, bool isSupported, bool supportsMultisample,
-                             uint8_t componentCount) {
+                             bool isRenderable, UnsupportedReason unsupportedReason,
+                             bool supportsMultisample, uint8_t componentCount) {
             Format internalFormat;
             internalFormat.format = format;
             internalFormat.baseFormat = format;
             internalFormat.isRenderable = isRenderable;
             internalFormat.isCompressed = false;
-            internalFormat.isSupported = isSupported;
+            internalFormat.unsupportedReason = unsupportedReason;
             internalFormat.supportsStorageUsage = false;
             internalFormat.supportsMultisample = supportsMultisample;
             internalFormat.supportsResolveTarget = false;
@@ -377,7 +397,7 @@
 
         bool BGRA8UnormSupportsStorageUsage = device->HasFeature(Feature::BGRA8UnormStorage);
         AddColorFormat(wgpu::TextureFormat::BGRA8Unorm, true, BGRA8UnormSupportsStorageUsage, true, true, 4, kAnyFloat, 4, 8, 1);
-        AddColorFormat(wgpu::TextureFormat::BGRA8UnormSrgb, true, false, true, true, 4, kAnyFloat, 4, 8, 1, wgpu::TextureFormat::BGRA8Unorm);
+        AddConditionalColorFormat(wgpu::TextureFormat::BGRA8UnormSrgb, device->IsCompatibilityMode() ? UnsupportedReason(CompatibilityMode{}) : Format::supported, true, false, true, true, 4, kAnyFloat, 4, 8, 1, wgpu::TextureFormat::BGRA8Unorm);
         AddColorFormat(wgpu::TextureFormat::RGB10A2Unorm, true, false, true, true, 4, kAnyFloat, 4, 8, 4);
 
         bool isRG11B10UfloatRenderable = device->HasFeature(Feature::RG11B10UfloatRenderable);
@@ -398,93 +418,120 @@
         AddColorFormat(wgpu::TextureFormat::RGBA32Float, true, true, false, false, 16, sampleTypeFor32BitFloatFormats, 4, 16, 4);
 
         // Depth-stencil formats
-        AddStencilFormat(wgpu::TextureFormat::Stencil8, true);
-        AddDepthFormat(wgpu::TextureFormat::Depth16Unorm, 2, true);
+        AddStencilFormat(wgpu::TextureFormat::Stencil8, Format::supported);
+        AddDepthFormat(wgpu::TextureFormat::Depth16Unorm, 2, Format::supported);
         // TODO(crbug.com/dawn/843): This is 4 because we read this to perform zero initialization,
         // and textures are always use depth32float. We should improve this to be more robust. Perhaps,
         // using 0 here to mean "unsized" and adding a backend-specific query for the block size.
-        AddDepthFormat(wgpu::TextureFormat::Depth24Plus, 4, true);
+        AddDepthFormat(wgpu::TextureFormat::Depth24Plus, 4, Format::supported);
         AddMultiAspectFormat(wgpu::TextureFormat::Depth24PlusStencil8,
-                              Aspect::Depth | Aspect::Stencil, wgpu::TextureFormat::Depth24Plus, wgpu::TextureFormat::Stencil8, true, true, true, 2);
-        AddDepthFormat(wgpu::TextureFormat::Depth32Float, 4, true);
-        bool isD32S8Supported = device->HasFeature(Feature::Depth32FloatStencil8);
+                              Aspect::Depth | Aspect::Stencil, wgpu::TextureFormat::Depth24Plus, wgpu::TextureFormat::Stencil8, true, Format::supported, true, 2);
+        AddDepthFormat(wgpu::TextureFormat::Depth32Float, 4, Format::supported);
+        UnsupportedReason d32s8UnsupportedReason = device->HasFeature(Feature::Depth32FloatStencil8) ? Format::supported : RequiresFeature{wgpu::FeatureName::Depth32FloatStencil8};
         AddMultiAspectFormat(wgpu::TextureFormat::Depth32FloatStencil8,
-                              Aspect::Depth | Aspect::Stencil, wgpu::TextureFormat::Depth32Float, wgpu::TextureFormat::Stencil8, true, isD32S8Supported, true, 2);
+                              Aspect::Depth | Aspect::Stencil, wgpu::TextureFormat::Depth32Float, wgpu::TextureFormat::Stencil8, true, d32s8UnsupportedReason, true, 2);
 
         // BC compressed formats
-        bool isBCFormatSupported = device->HasFeature(Feature::TextureCompressionBC);
-        AddCompressedFormat(wgpu::TextureFormat::BC1RGBAUnorm, 8, 4, 4, isBCFormatSupported, 4);
-        AddCompressedFormat(wgpu::TextureFormat::BC1RGBAUnormSrgb, 8, 4, 4, isBCFormatSupported, 4, wgpu::TextureFormat::BC1RGBAUnorm);
-        AddCompressedFormat(wgpu::TextureFormat::BC4RSnorm, 8, 4, 4, isBCFormatSupported, 1);
-        AddCompressedFormat(wgpu::TextureFormat::BC4RUnorm, 8, 4, 4, isBCFormatSupported, 1);
-        AddCompressedFormat(wgpu::TextureFormat::BC2RGBAUnorm, 16, 4, 4, isBCFormatSupported, 4);
-        AddCompressedFormat(wgpu::TextureFormat::BC2RGBAUnormSrgb, 16, 4, 4, isBCFormatSupported, 4, wgpu::TextureFormat::BC2RGBAUnorm);
-        AddCompressedFormat(wgpu::TextureFormat::BC3RGBAUnorm, 16, 4, 4, isBCFormatSupported, 4);
-        AddCompressedFormat(wgpu::TextureFormat::BC3RGBAUnormSrgb, 16, 4, 4, isBCFormatSupported, 4, wgpu::TextureFormat::BC3RGBAUnorm);
-        AddCompressedFormat(wgpu::TextureFormat::BC5RGSnorm, 16, 4, 4, isBCFormatSupported, 2);
-        AddCompressedFormat(wgpu::TextureFormat::BC5RGUnorm, 16, 4, 4, isBCFormatSupported, 2);
-        AddCompressedFormat(wgpu::TextureFormat::BC6HRGBFloat, 16, 4, 4, isBCFormatSupported, 3);
-        AddCompressedFormat(wgpu::TextureFormat::BC6HRGBUfloat, 16, 4, 4, isBCFormatSupported, 3);
-        AddCompressedFormat(wgpu::TextureFormat::BC7RGBAUnorm, 16, 4, 4, isBCFormatSupported, 4);
-        AddCompressedFormat(wgpu::TextureFormat::BC7RGBAUnormSrgb, 16, 4, 4, isBCFormatSupported, 4, wgpu::TextureFormat::BC7RGBAUnorm);
+        UnsupportedReason bcFormatUnsupportedReason = device->HasFeature(Feature::TextureCompressionBC) ? Format::supported : RequiresFeature{wgpu::FeatureName::TextureCompressionBC};
+        AddCompressedFormat(wgpu::TextureFormat::BC1RGBAUnorm, 8, 4, 4, bcFormatUnsupportedReason, 4);
+        AddCompressedFormat(wgpu::TextureFormat::BC1RGBAUnormSrgb, 8, 4, 4, bcFormatUnsupportedReason, 4, wgpu::TextureFormat::BC1RGBAUnorm);
+        AddCompressedFormat(wgpu::TextureFormat::BC4RSnorm, 8, 4, 4, bcFormatUnsupportedReason, 1);
+        AddCompressedFormat(wgpu::TextureFormat::BC4RUnorm, 8, 4, 4, bcFormatUnsupportedReason, 1);
+        AddCompressedFormat(wgpu::TextureFormat::BC2RGBAUnorm, 16, 4, 4, bcFormatUnsupportedReason, 4);
+        AddCompressedFormat(wgpu::TextureFormat::BC2RGBAUnormSrgb, 16, 4, 4, bcFormatUnsupportedReason, 4, wgpu::TextureFormat::BC2RGBAUnorm);
+        AddCompressedFormat(wgpu::TextureFormat::BC3RGBAUnorm, 16, 4, 4, bcFormatUnsupportedReason, 4);
+        AddCompressedFormat(wgpu::TextureFormat::BC3RGBAUnormSrgb, 16, 4, 4, bcFormatUnsupportedReason, 4, wgpu::TextureFormat::BC3RGBAUnorm);
+        AddCompressedFormat(wgpu::TextureFormat::BC5RGSnorm, 16, 4, 4, bcFormatUnsupportedReason, 2);
+        AddCompressedFormat(wgpu::TextureFormat::BC5RGUnorm, 16, 4, 4, bcFormatUnsupportedReason, 2);
+        AddCompressedFormat(wgpu::TextureFormat::BC6HRGBFloat, 16, 4, 4, bcFormatUnsupportedReason, 3);
+        AddCompressedFormat(wgpu::TextureFormat::BC6HRGBUfloat, 16, 4, 4, bcFormatUnsupportedReason, 3);
+        AddCompressedFormat(wgpu::TextureFormat::BC7RGBAUnorm, 16, 4, 4, bcFormatUnsupportedReason, 4);
+        AddCompressedFormat(wgpu::TextureFormat::BC7RGBAUnormSrgb, 16, 4, 4, bcFormatUnsupportedReason, 4, wgpu::TextureFormat::BC7RGBAUnorm);
 
         // ETC2/EAC compressed formats
-        bool isETC2FormatSupported = device->HasFeature(Feature::TextureCompressionETC2);
-        AddCompressedFormat(wgpu::TextureFormat::ETC2RGB8Unorm, 8, 4, 4, isETC2FormatSupported, 3);
-        AddCompressedFormat(wgpu::TextureFormat::ETC2RGB8UnormSrgb, 8, 4, 4, isETC2FormatSupported, 3, wgpu::TextureFormat::ETC2RGB8Unorm);
-        AddCompressedFormat(wgpu::TextureFormat::ETC2RGB8A1Unorm, 8, 4, 4, isETC2FormatSupported, 4);
-        AddCompressedFormat(wgpu::TextureFormat::ETC2RGB8A1UnormSrgb, 8, 4, 4, isETC2FormatSupported, 4, wgpu::TextureFormat::ETC2RGB8A1Unorm);
-        AddCompressedFormat(wgpu::TextureFormat::ETC2RGBA8Unorm, 16, 4, 4, isETC2FormatSupported, 4);
-        AddCompressedFormat(wgpu::TextureFormat::ETC2RGBA8UnormSrgb, 16, 4, 4, isETC2FormatSupported, 4, wgpu::TextureFormat::ETC2RGBA8Unorm);
-        AddCompressedFormat(wgpu::TextureFormat::EACR11Unorm, 8, 4, 4, isETC2FormatSupported, 1);
-        AddCompressedFormat(wgpu::TextureFormat::EACR11Snorm, 8, 4, 4, isETC2FormatSupported, 1);
-        AddCompressedFormat(wgpu::TextureFormat::EACRG11Unorm, 16, 4, 4, isETC2FormatSupported, 2);
-        AddCompressedFormat(wgpu::TextureFormat::EACRG11Snorm, 16, 4, 4, isETC2FormatSupported, 2);
+        UnsupportedReason etc2FormatUnsupportedReason = device->HasFeature(Feature::TextureCompressionETC2) ?  Format::supported : RequiresFeature{wgpu::FeatureName::TextureCompressionETC2};
+        AddCompressedFormat(wgpu::TextureFormat::ETC2RGB8Unorm, 8, 4, 4, etc2FormatUnsupportedReason, 3);
+        AddCompressedFormat(wgpu::TextureFormat::ETC2RGB8UnormSrgb, 8, 4, 4, etc2FormatUnsupportedReason, 3, wgpu::TextureFormat::ETC2RGB8Unorm);
+        AddCompressedFormat(wgpu::TextureFormat::ETC2RGB8A1Unorm, 8, 4, 4, etc2FormatUnsupportedReason, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ETC2RGB8A1UnormSrgb, 8, 4, 4, etc2FormatUnsupportedReason, 4, wgpu::TextureFormat::ETC2RGB8A1Unorm);
+        AddCompressedFormat(wgpu::TextureFormat::ETC2RGBA8Unorm, 16, 4, 4, etc2FormatUnsupportedReason, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ETC2RGBA8UnormSrgb, 16, 4, 4, etc2FormatUnsupportedReason, 4, wgpu::TextureFormat::ETC2RGBA8Unorm);
+        AddCompressedFormat(wgpu::TextureFormat::EACR11Unorm, 8, 4, 4, etc2FormatUnsupportedReason, 1);
+        AddCompressedFormat(wgpu::TextureFormat::EACR11Snorm, 8, 4, 4, etc2FormatUnsupportedReason, 1);
+        AddCompressedFormat(wgpu::TextureFormat::EACRG11Unorm, 16, 4, 4, etc2FormatUnsupportedReason, 2);
+        AddCompressedFormat(wgpu::TextureFormat::EACRG11Snorm, 16, 4, 4, etc2FormatUnsupportedReason, 2);
 
         // ASTC compressed formats
-        bool isASTCFormatSupported = device->HasFeature(Feature::TextureCompressionASTC);
-        AddCompressedFormat(wgpu::TextureFormat::ASTC4x4Unorm, 16, 4, 4, isASTCFormatSupported, 4);
-        AddCompressedFormat(wgpu::TextureFormat::ASTC4x4UnormSrgb, 16, 4, 4, isASTCFormatSupported, 4, wgpu::TextureFormat::ASTC4x4Unorm);
-        AddCompressedFormat(wgpu::TextureFormat::ASTC5x4Unorm, 16, 5, 4, isASTCFormatSupported, 4);
-        AddCompressedFormat(wgpu::TextureFormat::ASTC5x4UnormSrgb, 16, 5, 4, isASTCFormatSupported, 4, wgpu::TextureFormat::ASTC5x4Unorm);
-        AddCompressedFormat(wgpu::TextureFormat::ASTC5x5Unorm, 16, 5, 5, isASTCFormatSupported, 4);
-        AddCompressedFormat(wgpu::TextureFormat::ASTC5x5UnormSrgb, 16, 5, 5, isASTCFormatSupported, 4, wgpu::TextureFormat::ASTC5x5Unorm);
-        AddCompressedFormat(wgpu::TextureFormat::ASTC6x5Unorm, 16, 6, 5, isASTCFormatSupported, 4);
-        AddCompressedFormat(wgpu::TextureFormat::ASTC6x5UnormSrgb, 16, 6, 5, isASTCFormatSupported, 4, wgpu::TextureFormat::ASTC6x5Unorm);
-        AddCompressedFormat(wgpu::TextureFormat::ASTC6x6Unorm, 16, 6, 6, isASTCFormatSupported, 4);
-        AddCompressedFormat(wgpu::TextureFormat::ASTC6x6UnormSrgb, 16, 6, 6, isASTCFormatSupported, 4, wgpu::TextureFormat::ASTC6x6Unorm);
-        AddCompressedFormat(wgpu::TextureFormat::ASTC8x5Unorm, 16, 8, 5, isASTCFormatSupported, 4);
-        AddCompressedFormat(wgpu::TextureFormat::ASTC8x5UnormSrgb, 16, 8, 5, isASTCFormatSupported, 4, wgpu::TextureFormat::ASTC8x5Unorm);
-        AddCompressedFormat(wgpu::TextureFormat::ASTC8x6Unorm, 16, 8, 6, isASTCFormatSupported, 4);
-        AddCompressedFormat(wgpu::TextureFormat::ASTC8x6UnormSrgb, 16, 8, 6, isASTCFormatSupported, 4, wgpu::TextureFormat::ASTC8x6Unorm);
-        AddCompressedFormat(wgpu::TextureFormat::ASTC8x8Unorm, 16, 8, 8, isASTCFormatSupported, 4);
-        AddCompressedFormat(wgpu::TextureFormat::ASTC8x8UnormSrgb, 16, 8, 8, isASTCFormatSupported, 4, wgpu::TextureFormat::ASTC8x8Unorm);
-        AddCompressedFormat(wgpu::TextureFormat::ASTC10x5Unorm, 16, 10, 5, isASTCFormatSupported, 4);
-        AddCompressedFormat(wgpu::TextureFormat::ASTC10x5UnormSrgb, 16, 10, 5, isASTCFormatSupported, 4, wgpu::TextureFormat::ASTC10x5Unorm);
-        AddCompressedFormat(wgpu::TextureFormat::ASTC10x6Unorm, 16, 10, 6, isASTCFormatSupported, 4);
-        AddCompressedFormat(wgpu::TextureFormat::ASTC10x6UnormSrgb, 16, 10, 6, isASTCFormatSupported, 4, wgpu::TextureFormat::ASTC10x6Unorm);
-        AddCompressedFormat(wgpu::TextureFormat::ASTC10x8Unorm, 16, 10, 8, isASTCFormatSupported, 4);
-        AddCompressedFormat(wgpu::TextureFormat::ASTC10x8UnormSrgb, 16, 10, 8, isASTCFormatSupported, 4, wgpu::TextureFormat::ASTC10x8Unorm);
-        AddCompressedFormat(wgpu::TextureFormat::ASTC10x10Unorm, 16, 10, 10, isASTCFormatSupported, 4);
-        AddCompressedFormat(wgpu::TextureFormat::ASTC10x10UnormSrgb, 16, 10, 10, isASTCFormatSupported, 4, wgpu::TextureFormat::ASTC10x10Unorm);
-        AddCompressedFormat(wgpu::TextureFormat::ASTC12x10Unorm, 16, 12, 10, isASTCFormatSupported, 4);
-        AddCompressedFormat(wgpu::TextureFormat::ASTC12x10UnormSrgb, 16, 12, 10, isASTCFormatSupported, 4, wgpu::TextureFormat::ASTC12x10Unorm);
-        AddCompressedFormat(wgpu::TextureFormat::ASTC12x12Unorm, 16, 12, 12, isASTCFormatSupported, 4);
-        AddCompressedFormat(wgpu::TextureFormat::ASTC12x12UnormSrgb, 16, 12, 12, isASTCFormatSupported, 4, wgpu::TextureFormat::ASTC12x12Unorm);
+        UnsupportedReason astcFormatUnsupportedReason = device->HasFeature(Feature::TextureCompressionASTC) ?  Format::supported : RequiresFeature{wgpu::FeatureName::TextureCompressionASTC};
+        AddCompressedFormat(wgpu::TextureFormat::ASTC4x4Unorm, 16, 4, 4, astcFormatUnsupportedReason, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC4x4UnormSrgb, 16, 4, 4, astcFormatUnsupportedReason, 4, wgpu::TextureFormat::ASTC4x4Unorm);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC5x4Unorm, 16, 5, 4, astcFormatUnsupportedReason, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC5x4UnormSrgb, 16, 5, 4, astcFormatUnsupportedReason, 4, wgpu::TextureFormat::ASTC5x4Unorm);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC5x5Unorm, 16, 5, 5, astcFormatUnsupportedReason, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC5x5UnormSrgb, 16, 5, 5, astcFormatUnsupportedReason, 4, wgpu::TextureFormat::ASTC5x5Unorm);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC6x5Unorm, 16, 6, 5, astcFormatUnsupportedReason, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC6x5UnormSrgb, 16, 6, 5, astcFormatUnsupportedReason, 4, wgpu::TextureFormat::ASTC6x5Unorm);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC6x6Unorm, 16, 6, 6, astcFormatUnsupportedReason, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC6x6UnormSrgb, 16, 6, 6, astcFormatUnsupportedReason, 4, wgpu::TextureFormat::ASTC6x6Unorm);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC8x5Unorm, 16, 8, 5, astcFormatUnsupportedReason, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC8x5UnormSrgb, 16, 8, 5, astcFormatUnsupportedReason, 4, wgpu::TextureFormat::ASTC8x5Unorm);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC8x6Unorm, 16, 8, 6, astcFormatUnsupportedReason, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC8x6UnormSrgb, 16, 8, 6, astcFormatUnsupportedReason, 4, wgpu::TextureFormat::ASTC8x6Unorm);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC8x8Unorm, 16, 8, 8, astcFormatUnsupportedReason, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC8x8UnormSrgb, 16, 8, 8, astcFormatUnsupportedReason, 4, wgpu::TextureFormat::ASTC8x8Unorm);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC10x5Unorm, 16, 10, 5, astcFormatUnsupportedReason, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC10x5UnormSrgb, 16, 10, 5, astcFormatUnsupportedReason, 4, wgpu::TextureFormat::ASTC10x5Unorm);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC10x6Unorm, 16, 10, 6, astcFormatUnsupportedReason, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC10x6UnormSrgb, 16, 10, 6, astcFormatUnsupportedReason, 4, wgpu::TextureFormat::ASTC10x6Unorm);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC10x8Unorm, 16, 10, 8, astcFormatUnsupportedReason, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC10x8UnormSrgb, 16, 10, 8, astcFormatUnsupportedReason, 4, wgpu::TextureFormat::ASTC10x8Unorm);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC10x10Unorm, 16, 10, 10, astcFormatUnsupportedReason, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC10x10UnormSrgb, 16, 10, 10, astcFormatUnsupportedReason, 4, wgpu::TextureFormat::ASTC10x10Unorm);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC12x10Unorm, 16, 12, 10, astcFormatUnsupportedReason, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC12x10UnormSrgb, 16, 12, 10, astcFormatUnsupportedReason, 4, wgpu::TextureFormat::ASTC12x10Unorm);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC12x12Unorm, 16, 12, 12, astcFormatUnsupportedReason, 4);
+        AddCompressedFormat(wgpu::TextureFormat::ASTC12x12UnormSrgb, 16, 12, 12, astcFormatUnsupportedReason, 4, wgpu::TextureFormat::ASTC12x12Unorm);
 
         // multi-planar formats
-        const bool isMultiPlanarFormatSupported = device->HasFeature(Feature::MultiPlanarFormats);
+        const UnsupportedReason multiPlanarFormatUnsupportedReason = device->HasFeature(Feature::MultiPlanarFormats) ?  Format::supported : RequiresFeature{wgpu::FeatureName::DawnMultiPlanarFormats};
         AddMultiAspectFormat(wgpu::TextureFormat::R8BG8Biplanar420Unorm, Aspect::Plane0 | Aspect::Plane1,
-            wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::RG8Unorm, false, isMultiPlanarFormatSupported, false, 3);
+            wgpu::TextureFormat::R8Unorm, wgpu::TextureFormat::RG8Unorm, false, multiPlanarFormatUnsupportedReason, false, 3);
 
-    // clang-format on
+        // clang-format on
 
-    // This checks that each format is set at least once, the second part of checking that all
-    // formats are checked exactly once. If this assertion is failing and texture formats have been
-    // added or removed recently, check that kKnownFormatCount has been updated.
-    ASSERT(formatsSet.all());
+        // This checks that each format is set at least once, the second part of checking that all
+        // formats are checked exactly once. If this assertion is failing and texture formats have
+        // been added or removed recently, check that kKnownFormatCount has been updated.
+        ASSERT(formatsSet.all());
 
-    return table;
+        return table;
+}
+
+namespace {
+
+template <class... Ts>
+struct overloaded : Ts... {
+        using Ts::operator()...;
+};
+template <class... Ts>
+overloaded(Ts...) -> overloaded<Ts...>;
+
+}  // anonymous namespace
+
+absl::FormatConvertResult<absl::FormatConversionCharSet::kString> AbslFormatConvert(
+    const UnsupportedReason& value,
+    const absl::FormatConversionSpec& spec,
+    absl::FormatSink* s) {
+        std::visit(overloaded{[](const std::monostate&) { UNREACHABLE(); },
+                              [s](const RequiresFeature& requiresFeature) {
+                                  s->Append(absl::StrFormat("requires feature %s",
+                                                            requiresFeature.feature));
+                              },
+                              [s](const CompatibilityMode&) {
+                                  s->Append("not supported in compatibility mode");
+                              }},
+                   value);
+        return {true};
 }
 
 }  // namespace dawn::native
diff --git a/src/dawn/native/Format.h b/src/dawn/native/Format.h
index 615ab35..9d6be4c 100644
--- a/src/dawn/native/Format.h
+++ b/src/dawn/native/Format.h
@@ -16,6 +16,7 @@
 #define SRC_DAWN_NATIVE_FORMAT_H_
 
 #include <array>
+#include <variant>
 
 #include "dawn/native/dawn_platform.h"
 
@@ -26,6 +27,8 @@
 #include "dawn/native/Error.h"
 #include "dawn/native/Subresource.h"
 
+#include "absl/strings/str_format.h"
+
 // About multi-planar formats.
 //
 // Dawn supports additional multi-planar formats when the multiplanar-formats extension is enabled.
@@ -72,6 +75,15 @@
     Uint,
 };
 
+struct RequiresFeature {
+    wgpu::FeatureName feature;
+};
+
+struct CompatibilityMode {};
+
+using UnsupportedReason =
+    std::variant</* is supported */ std::monostate, RequiresFeature, CompatibilityMode>;
+
 struct AspectInfo {
     TexelBlockInfo block;
     TextureComponentType baseType{};
@@ -92,11 +104,13 @@
 struct Format {
     wgpu::TextureFormat format = wgpu::TextureFormat::Undefined;
 
+    static const UnsupportedReason supported;
+
     // TODO(crbug.com/dawn/1332): These members could be stored in a Format capability matrix.
     bool isRenderable = false;
     bool isCompressed = false;
     // A format can be known but not supported because it is part of a disabled extension.
-    bool isSupported = false;
+    UnsupportedReason unsupportedReason;
     bool supportsStorageUsage = false;
     bool supportsMultisample = false;
     bool supportsResolveTarget = false;
@@ -106,6 +120,7 @@
     uint8_t renderTargetPixelByteCost = 0;       // byte cost of pixel in render targets
     uint8_t renderTargetComponentAlignment = 0;  // byte alignment for components in render targets
 
+    bool IsSupported() const;
     bool IsColor() const;
     bool HasDepth() const;
     bool HasStencil() const;
@@ -164,6 +179,11 @@
 // Builds the format table with the extensions enabled on the device.
 FormatTable BuildFormatTable(const DeviceBase* device);
 
+absl::FormatConvertResult<absl::FormatConversionCharSet::kString> AbslFormatConvert(
+    const UnsupportedReason& value,
+    const absl::FormatConversionSpec& spec,
+    absl::FormatSink* s);
+
 }  // namespace dawn::native
 
 namespace dawn {
diff --git a/src/dawn/native/opengl/DeviceGL.cpp b/src/dawn/native/opengl/DeviceGL.cpp
index 4b0cf82..35f8dd3 100644
--- a/src/dawn/native/opengl/DeviceGL.cpp
+++ b/src/dawn/native/opengl/DeviceGL.cpp
@@ -177,7 +177,7 @@
 }
 
 const GLFormat& Device::GetGLFormat(const Format& format) {
-    ASSERT(format.isSupported);
+    ASSERT(format.IsSupported());
     ASSERT(format.GetIndex() < mFormatTable.size());
 
     const GLFormat& result = mFormatTable[format.GetIndex()];
diff --git a/src/dawn/tests/unittests/validation/CompatValidationTests.cpp b/src/dawn/tests/unittests/validation/CompatValidationTests.cpp
index 0cb8042..b5350d4 100644
--- a/src/dawn/tests/unittests/validation/CompatValidationTests.cpp
+++ b/src/dawn/tests/unittests/validation/CompatValidationTests.cpp
@@ -882,6 +882,32 @@
         });
 }
 
+TEST_F(CompatValidationTest, CanNotCreateBGRA8UnormSRGBTexture) {
+    wgpu::TextureDescriptor descriptor;
+    descriptor.size = {1, 1, 1};
+    descriptor.dimension = wgpu::TextureDimension::e2D;
+    descriptor.format = wgpu::TextureFormat::BGRA8UnormSrgb;
+    descriptor.usage = wgpu::TextureUsage::TextureBinding;
+
+    ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor),
+                        testing::HasSubstr("not supported in compatibility mode"));
+}
+
+TEST_F(CompatValidationTest, CanNotCreateBGRA8UnormTextureWithBGRA8UnormSrgbView) {
+    constexpr wgpu::TextureFormat viewFormat = wgpu::TextureFormat::BGRA8UnormSrgb;
+
+    wgpu::TextureDescriptor descriptor;
+    descriptor.size = {1, 1, 1};
+    descriptor.dimension = wgpu::TextureDimension::e2D;
+    descriptor.format = wgpu::TextureFormat::BGRA8Unorm;
+    descriptor.usage = wgpu::TextureUsage::TextureBinding;
+    descriptor.viewFormatCount = 1;
+    descriptor.viewFormats = &viewFormat;
+
+    ASSERT_DEVICE_ERROR(device.CreateTexture(&descriptor),
+                        testing::HasSubstr("not supported in compatibility mode"));
+}
+
 class CompatCompressedTextureToBufferCopyValidationTests : public CompatValidationTest {
   protected:
     WGPUDevice CreateTestDevice(native::Adapter dawnAdapter,