Add VulkanClearGen12TextureWithCCSAmbiguateOnCreation toggle

This works around an Intel Gen12 mesa driver bug by clearing some
R8 textures on creation to mitigate the buggy CCS ambiguates.

Bug: chromium:1361662

Change-Id: I7311275d0c9fc5928985e2a51b4eb7b30459b493
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/124200
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Jie A Chen <jie.a.chen@intel.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/dawn/native/Toggles.cpp b/src/dawn/native/Toggles.cpp
index cd802ff..ca22e07 100644
--- a/src/dawn/native/Toggles.cpp
+++ b/src/dawn/native/Toggles.cpp
@@ -392,6 +392,11 @@
       "Polyfill the reflect builtin for vec2<f32> for D3D12. This toggle is enabled by default on "
       "D3D12 backends using FXC on Intel GPUs due to a driver issue on Intel D3D12 driver.",
       "https://crbug.com/tint/1798", ToggleStage::Device}},
+    {Toggle::VulkanClearGen12TextureWithCCSAmbiguateOnCreation,
+     {"vulkan_clear_gen12_texture_with_ccs_ambiguate_on_creation",
+      "Clears some R8-like textures to full 0 bits as soon as they are created. This Toggle is "
+      "enabled on Intel Gen12 GPUs due to a mesa driver issue.",
+      "https://crbug.com/chromium/1361662", ToggleStage::Device}},
     {Toggle::NoWorkaroundSampleMaskBecomesZeroForAllButLastColorTarget,
      {"no_workaround_sample_mask_becomes_zero_for_all_but_last_color_target",
       "MacOS 12.0+ Intel has a bug where the sample mask is only applied for the last color "
diff --git a/src/dawn/native/Toggles.h b/src/dawn/native/Toggles.h
index 0eab485..be459a7 100644
--- a/src/dawn/native/Toggles.h
+++ b/src/dawn/native/Toggles.h
@@ -93,6 +93,7 @@
     D3D12ReplaceAddWithMinusWhenDstFactorIsZeroAndSrcFactorIsDstAlpha,
     AllowDeprecatedAPIs,
     D3D12PolyfillReflectVec2F32,
+    VulkanClearGen12TextureWithCCSAmbiguateOnCreation,
 
     // Unresolved issues.
     NoWorkaroundSampleMaskBecomesZeroForAllButLastColorTarget,
diff --git a/src/dawn/native/vulkan/AdapterVk.cpp b/src/dawn/native/vulkan/AdapterVk.cpp
index cec496a..af227af 100644
--- a/src/dawn/native/vulkan/AdapterVk.cpp
+++ b/src/dawn/native/vulkan/AdapterVk.cpp
@@ -420,11 +420,18 @@
         // dawn:1688: Intel Mesa driver has a bug about reusing the VkDeviceMemory that was
         // previously bound to a 2D VkImage. To work around that bug we have to disable the resource
         // sub-allocation for 2D textures with CopyDst or RenderAttachment usage.
-        const gpu_info::DriverVersion kDriverVersion = {21, 3, 6, 0};
-        if (gpu_info::CompareIntelMesaDriverVersion(GetDriverVersion(), kDriverVersion) >= 0) {
+        const gpu_info::DriverVersion kBuggyDriverVersion = {21, 3, 6, 0};
+        if (gpu_info::CompareIntelMesaDriverVersion(GetDriverVersion(), kBuggyDriverVersion) >= 0) {
             deviceToggles->Default(
                 Toggle::DisableSubAllocationFor2DTextureWithCopyDstOrRenderAttachment, true);
         }
+
+        // chromium:1361662: Mesa driver has a bug clearing R8 mip-leveled textures on Intel Gen12
+        // GPUs. Work around it by clearing the whole texture as soon as they are created.
+        const gpu_info::DriverVersion kFixedDriverVersion = {23, 1, 0, 0};
+        if (gpu_info::CompareIntelMesaDriverVersion(GetDriverVersion(), kFixedDriverVersion) < 0) {
+            deviceToggles->Default(Toggle::VulkanClearGen12TextureWithCCSAmbiguateOnCreation, true);
+        }
     }
 
     // The environment can request to various options for depth-stencil formats that could be
diff --git a/src/dawn/native/vulkan/TextureVk.cpp b/src/dawn/native/vulkan/TextureVk.cpp
index 2e767a7..1f7a9a9 100644
--- a/src/dawn/native/vulkan/TextureVk.cpp
+++ b/src/dawn/native/vulkan/TextureVk.cpp
@@ -745,6 +745,26 @@
                                    mMemoryAllocation.GetOffset()),
         "BindImageMemory"));
 
+    // crbug.com/1361662
+    // This works around an Intel Gen12 mesa bug due to CCS ambiguates stomping on each other.
+    // https://gitlab.freedesktop.org/mesa/mesa/-/issues/7301#note_1826367
+    if (device->IsToggleEnabled(Toggle::VulkanClearGen12TextureWithCCSAmbiguateOnCreation)) {
+        auto format = GetFormat().format;
+        bool textureIsBuggy =
+            format == wgpu::TextureFormat::R8Unorm || format == wgpu::TextureFormat::R8Snorm ||
+            format == wgpu::TextureFormat::R8Uint || format == wgpu::TextureFormat::R8Sint ||
+            // These are flaky.
+            format == wgpu::TextureFormat::RG16Sint || format == wgpu::TextureFormat::RGBA16Sint ||
+            format == wgpu::TextureFormat::RGBA32Float;
+        textureIsBuggy &= GetNumMipLevels() > 1;
+        textureIsBuggy &= GetDimension() == wgpu::TextureDimension::e2D;
+        textureIsBuggy &= IsPowerOfTwo(GetWidth()) && IsPowerOfTwo(GetHeight());
+        if (textureIsBuggy) {
+            DAWN_TRY(ClearTexture(ToBackend(GetDevice())->GetPendingRecordingContext(),
+                                  GetAllSubresources(), TextureBase::ClearValue::Zero));
+        }
+    }
+
     if (device->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting)) {
         DAWN_TRY(ClearTexture(ToBackend(GetDevice())->GetPendingRecordingContext(),
                               GetAllSubresources(), TextureBase::ClearValue::NonZero));