[dawn] Add SubgroupMatrixConfigs to adapter info

No devices support the feature yet, but we can still test that the
query fails if the feature is not supported and that the wire client
handles the query correctly.

Bug: 348702031
Change-Id: I0d5858e4e0cb87c4ad64e4405b5fb187223db731
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/225414
Commit-Queue: James Price <jrprice@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn/dawn.json b/src/dawn/dawn.json
index f99b6b6..4f627f9 100644
--- a/src/dawn/dawn.json
+++ b/src/dawn/dawn.json
@@ -3720,7 +3720,8 @@
             {"value": 56, "name": "shared texture memory a hardware buffer properties", "tags": ["dawn", "native"]},
             {"value": 57, "name": "a hardware buffer properties", "tags": ["dawn", "native"]},
             {"value": 58, "name": "dawn experimental immediate data limits", "tags": ["dawn"]},
-            {"value": 59, "name": "dawn texel copy buffer row alignment limits", "tags": ["dawn"]}
+            {"value": 59, "name": "dawn texel copy buffer row alignment limits", "tags": ["dawn"]},
+            {"value": 60, "name": "adapter properties subgroup matrix configs", "tags": ["dawn"]}
         ]
     },
     "texture": {
@@ -4288,5 +4289,36 @@
         "members": [
             {"name": "out of memory", "type": "bool", "default": "false"}
         ]
+    },
+    "subgroup matrix component type": {
+        "category": "enum",
+        "emscripten_no_enum_table": true,
+        "values": [
+            {"value": 1, "name": "f32"},
+            {"value": 2, "name": "f16"},
+            {"value": 3, "name": "u32"},
+            {"value": 4, "name": "i32"}
+        ]
+    },
+    "subgroup matrix config": {
+        "category": "structure",
+        "tags": ["dawn"],
+        "members": [
+            {"name": "component type", "type": "subgroup matrix component type"},
+            {"name": "result component type", "type": "subgroup matrix component type"},
+            {"name": "M", "type": "uint32_t"},
+            {"name": "N", "type": "uint32_t"},
+            {"name": "K", "type": "uint32_t"}
+        ]
+    },
+    "adapter properties subgroup matrix configs": {
+        "category": "structure",
+        "chained": "out",
+        "chain roots": ["adapter info"],
+        "tags": ["dawn"],
+        "members": [
+            {"name": "config count", "type": "size_t"},
+            {"name": "configs", "type": "subgroup matrix config", "annotation": "const*", "length": "config count"}
+        ]
     }
 }
diff --git a/src/dawn/native/Adapter.cpp b/src/dawn/native/Adapter.cpp
index 48e5162..cc68321 100644
--- a/src/dawn/native/Adapter.cpp
+++ b/src/dawn/native/Adapter.cpp
@@ -187,6 +187,11 @@
         hadError |= mInstance->ConsumedError(
             DAWN_VALIDATION_ERROR("Feature AdapterPropertiesVk is not available."));
     }
+    if (unpacked.Get<AdapterPropertiesSubgroupMatrixConfigs>() != nullptr &&
+        !mSupportedFeatures.IsEnabled(wgpu::FeatureName::ChromiumExperimentalSubgroupMatrix)) {
+        hadError |= mInstance->ConsumedError(
+            DAWN_VALIDATION_ERROR("Feature ChromiumExperimentalSubgroupMatrix is not available."));
+    }
     if (hadError) {
         return wgpu::Status::Error;
     }
@@ -261,6 +266,11 @@
     delete[] capabilities.properties;
 }
 
+void APIAdapterPropertiesSubgroupMatrixConfigsFreeMembers(
+    WGPUAdapterPropertiesSubgroupMatrixConfigs subgroupMatrixConfigs) {
+    delete[] subgroupMatrixConfigs.configs;
+}
+
 bool AdapterBase::APIHasFeature(wgpu::FeatureName feature) const {
     return mSupportedFeatures.IsEnabled(feature);
 }
diff --git a/src/dawn/tests/BUILD.gn b/src/dawn/tests/BUILD.gn
index 8c90b27..c06af25 100644
--- a/src/dawn/tests/BUILD.gn
+++ b/src/dawn/tests/BUILD.gn
@@ -667,6 +667,7 @@
     "end2end/ShaderTests.cpp",
     "end2end/ShaderValidationTests.cpp",
     "end2end/StorageTextureTests.cpp",
+    "end2end/SubgroupMatrixTests.cpp",
     "end2end/SubgroupsTests.cpp",
     "end2end/SubresourceRenderAttachmentTests.cpp",
     "end2end/Texture3DTests.cpp",
diff --git a/src/dawn/tests/end2end/SubgroupMatrixTests.cpp b/src/dawn/tests/end2end/SubgroupMatrixTests.cpp
new file mode 100644
index 0000000..d334b58
--- /dev/null
+++ b/src/dawn/tests/end2end/SubgroupMatrixTests.cpp
@@ -0,0 +1,62 @@
+// Copyright 2025 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+//    list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+//    this list of conditions and the following disclaimer in the documentation
+//    and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+//    contributors may be used to endorse or promote products derived from
+//    this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include <vector>
+
+#include "dawn/tests/DawnTest.h"
+
+namespace dawn {
+namespace {
+
+using SubgroupMatrixTest = DawnTest;
+
+// Test that it is only valid to request the AdapterPropertiesSubgroupMatrixConfigs structure if the
+// feature is available.
+TEST_P(SubgroupMatrixTest, QueryConfigsOnlyValidWithFeature) {
+    auto expected = adapter.HasFeature(wgpu::FeatureName::ChromiumExperimentalSubgroupMatrix)
+                        ? wgpu::Status::Success
+                        : wgpu::Status::Error;
+    {
+        wgpu::AdapterInfo info;
+        wgpu::AdapterPropertiesSubgroupMatrixConfigs subgroupMatrixConfigs;
+        info.nextInChain = &subgroupMatrixConfigs;
+
+        EXPECT_EQ(adapter.GetInfo(&info), expected);
+    }
+    {
+        wgpu::AdapterInfo adapterInfo;
+        wgpu::AdapterPropertiesSubgroupMatrixConfigs subgroupMatrixConfigs;
+        adapterInfo.nextInChain = &subgroupMatrixConfigs;
+
+        EXPECT_EQ(device.GetAdapterInfo(&adapterInfo), expected);
+    }
+}
+
+DAWN_INSTANTIATE_TEST(SubgroupMatrixTest, D3D12Backend(), MetalBackend(), VulkanBackend());
+
+}  // anonymous namespace
+}  // namespace dawn
diff --git a/src/dawn/tests/unittests/wire/WireInstanceTests.cpp b/src/dawn/tests/unittests/wire/WireInstanceTests.cpp
index cd17ea7..e2dadea4 100644
--- a/src/dawn/tests/unittests/wire/WireInstanceTests.cpp
+++ b/src/dawn/tests/unittests/wire/WireInstanceTests.cpp
@@ -242,19 +242,34 @@
     fakeSubgroupsProperties.subgroupMinSize = 4;
     fakeSubgroupsProperties.subgroupMaxSize = 128;
 
+    WGPUSubgroupMatrixConfig fakeMatrixConfigs[3] = {
+        {WGPUSubgroupMatrixComponentType_F32, WGPUSubgroupMatrixComponentType_F32, 8, 4, 2},
+        {WGPUSubgroupMatrixComponentType_U32, WGPUSubgroupMatrixComponentType_I32, 4, 8, 16},
+        {WGPUSubgroupMatrixComponentType_F16, WGPUSubgroupMatrixComponentType_F32, 2, 16, 4},
+    };
+
+    WGPUAdapterPropertiesSubgroupMatrixConfigs fakeSubgroupMatrixConfigs = {};
+    fakeSubgroupMatrixConfigs.chain.sType = WGPUSType_AdapterPropertiesSubgroupMatrixConfigs;
+    fakeSubgroupMatrixConfigs.configCount = 3;
+    fakeSubgroupMatrixConfigs.configs = fakeMatrixConfigs;
+
     std::initializer_list<WGPUFeatureName> fakeFeaturesList = {
         WGPUFeatureName_AdapterPropertiesMemoryHeaps,
         WGPUFeatureName_AdapterPropertiesD3D,
         WGPUFeatureName_AdapterPropertiesVk,
         WGPUFeatureName_Subgroups,
+        WGPUFeatureName_ChromiumExperimentalSubgroupMatrix,
     };
+    WGPUSupportedFeatures fakeFeatures = {fakeFeaturesList.size(), std::data(fakeFeaturesList)};
 
     // Expect the server to receive the message. Then, mock a fake reply.
     WGPUAdapter apiAdapter = api.GetNewAdapter();
     EXPECT_CALL(api, OnInstanceRequestAdapter(apiInstance, NotNull(), _))
         .WillOnce(InvokeWithoutArgs([&] {
             EXPECT_CALL(api, AdapterGetLimits(apiAdapter, NotNull())).Times(1);
-            EXPECT_CALL(api, AdapterGetFeatures(apiAdapter, NotNull())).Times(1);
+            EXPECT_CALL(api, AdapterGetFeatures(apiAdapter, NotNull()))
+                .WillOnce(WithArg<1>(
+                    Invoke([&](WGPUSupportedFeatures* features) { *features = fakeFeatures; })));
 
             for (WGPUFeatureName feature : fakeFeaturesList) {
                 EXPECT_CALL(api, AdapterHasFeature(apiAdapter, feature)).WillOnce(Return(true));
@@ -281,6 +296,10 @@
                                 *reinterpret_cast<WGPUAdapterPropertiesSubgroups*>(chain) =
                                     fakeSubgroupsProperties;
                                 break;
+                            case WGPUSType_AdapterPropertiesSubgroupMatrixConfigs:
+                                *reinterpret_cast<WGPUAdapterPropertiesSubgroupMatrixConfigs*>(
+                                    chain) = fakeSubgroupMatrixConfigs;
+                                break;
                             default:
                                 ADD_FAILURE() << "Unexpected chain";
                                 return WGPUStatus_Error;
@@ -352,6 +371,28 @@
                           fakeSubgroupsProperties.subgroupMinSize);
                 EXPECT_EQ(subgroupsProperties.subgroupMaxSize,
                           fakeSubgroupsProperties.subgroupMaxSize);
+
+                // Get the subgroup matrix properties.
+                WGPUAdapterPropertiesSubgroupMatrixConfigs subgroupMatrixConfigs = {};
+                subgroupMatrixConfigs.chain.sType =
+                    WGPUSType_AdapterPropertiesSubgroupMatrixConfigs;
+                info.nextInChain = &subgroupMatrixConfigs.chain;
+                adapter.GetInfo(reinterpret_cast<wgpu::AdapterInfo*>(&info));
+
+                // Expect everything matches the fake properties returned by the server.
+                EXPECT_EQ(subgroupMatrixConfigs.configCount, fakeSubgroupMatrixConfigs.configCount);
+                for (size_t i = 0; i < fakeSubgroupMatrixConfigs.configCount; ++i) {
+                    EXPECT_EQ(subgroupMatrixConfigs.configs[i].componentType,
+                              fakeSubgroupMatrixConfigs.configs[i].componentType);
+                    EXPECT_EQ(subgroupMatrixConfigs.configs[i].resultComponentType,
+                              fakeSubgroupMatrixConfigs.configs[i].resultComponentType);
+                    EXPECT_EQ(subgroupMatrixConfigs.configs[i].M,
+                              fakeSubgroupMatrixConfigs.configs[i].M);
+                    EXPECT_EQ(subgroupMatrixConfigs.configs[i].N,
+                              fakeSubgroupMatrixConfigs.configs[i].N);
+                    EXPECT_EQ(subgroupMatrixConfigs.configs[i].K,
+                              fakeSubgroupMatrixConfigs.configs[i].K);
+                }
             })));
 
         FlushCallbacks();
diff --git a/src/dawn/wire/client/Adapter.cpp b/src/dawn/wire/client/Adapter.cpp
index 4b264eb..dfd0125 100644
--- a/src/dawn/wire/client/Adapter.cpp
+++ b/src/dawn/wire/client/Adapter.cpp
@@ -189,6 +189,15 @@
                 mSubgroupsProperties.subgroupMaxSize = subgroupsProperties->subgroupMaxSize;
                 break;
             }
+            case WGPUSType_AdapterPropertiesSubgroupMatrixConfigs: {
+                // Make a copy of the heap info in `mSubgroupMatrixConfigs`.
+                const auto* subgroupMatrixConfigs =
+                    reinterpret_cast<const WGPUAdapterPropertiesSubgroupMatrixConfigs*>(chain);
+                mSubgroupMatrixConfigs = {
+                    subgroupMatrixConfigs->configs,
+                    subgroupMatrixConfigs->configs + subgroupMatrixConfigs->configCount};
+                break;
+            }
             default:
                 DAWN_UNREACHABLE();
                 break;
@@ -231,6 +240,23 @@
                 subgroupsProperties->subgroupMaxSize = mSubgroupsProperties.subgroupMaxSize;
                 break;
             }
+            case WGPUSType_AdapterPropertiesSubgroupMatrixConfigs: {
+                if (!HasFeature(WGPUFeatureName_ChromiumExperimentalSubgroupMatrix)) {
+                    return WGPUStatus_Error;
+                }
+
+                // Copy `mSubgroupMatrixConfigs` into a new allocation.
+                auto* subgroupMatrixConfigs =
+                    reinterpret_cast<WGPUAdapterPropertiesSubgroupMatrixConfigs*>(chain);
+                size_t configCount = mSubgroupMatrixConfigs.size();
+                auto* configs = new WGPUSubgroupMatrixConfig[configCount];
+                memcpy(configs, mSubgroupMatrixConfigs.data(),
+                       sizeof(WGPUSubgroupMatrixConfig) * configCount);
+                // Write out the pointer and count to the subgroup matrix configs out-struct.
+                subgroupMatrixConfigs->configCount = configCount;
+                subgroupMatrixConfigs->configs = configs;
+                break;
+            }
             default:
                 break;
         }
@@ -340,3 +366,8 @@
     WGPUSupportedFeatures supportedFeatures) {
     delete[] supportedFeatures.features;
 }
+
+DAWN_WIRE_EXPORT void wgpuDawnWireClientAdapterPropertiesSubgroupMatrixConfigsFreeMembers(
+    WGPUAdapterPropertiesSubgroupMatrixConfigs subgroupMatrixConfigs) {
+    delete[] subgroupMatrixConfigs.configs;
+}
diff --git a/src/dawn/wire/client/Adapter.h b/src/dawn/wire/client/Adapter.h
index e0fcfa6..c6e8d25 100644
--- a/src/dawn/wire/client/Adapter.h
+++ b/src/dawn/wire/client/Adapter.h
@@ -78,6 +78,7 @@
         4u,   // subgroupMinSize
         128u  // subgroupMaxSize
     };
+    std::vector<WGPUSubgroupMatrixConfig> mSubgroupMatrixConfigs;
 };
 
 }  // namespace dawn::wire::client
diff --git a/src/dawn/wire/server/ServerInstance.cpp b/src/dawn/wire/server/ServerInstance.cpp
index edf9dd1..225310c 100644
--- a/src/dawn/wire/server/ServerInstance.cpp
+++ b/src/dawn/wire/server/ServerInstance.cpp
@@ -121,6 +121,15 @@
         propertiesChain = &(*propertiesChain)->next;
     }
 
+    // Query AdapterPropertiesSubgroupMatrixConfigs if the feature is supported.
+    FreeMembers<WGPUAdapterPropertiesSubgroupMatrixConfigs> subgroupMatrixConfigs(mProcs);
+    // WGPUAdapterPropertiesSubgroupMatrixConfigs subgroupMatrixConfigs{};
+    subgroupMatrixConfigs.chain.sType = WGPUSType_AdapterPropertiesSubgroupMatrixConfigs;
+    if (mProcs.adapterHasFeature(adapter, WGPUFeatureName_ChromiumExperimentalSubgroupMatrix)) {
+        *propertiesChain = &subgroupMatrixConfigs.chain;
+        propertiesChain = &(*propertiesChain)->next;
+    }
+
     mProcs.adapterGetInfo(adapter, &info);
     cmd.info = &info;
 
diff --git a/tools/android/BUILD.gn b/tools/android/BUILD.gn
index 206a276..d2efcba 100644
--- a/tools/android/BUILD.gn
+++ b/tools/android/BUILD.gn
@@ -178,6 +178,7 @@
     "java/android/dawn/StorageTextureAccess.kt",
     "java/android/dawn/StorageTextureBindingLayout.kt",
     "java/android/dawn/StoreOp.kt",
+    "java/android/dawn/SubgroupMatrixComponentType.kt",
     "java/android/dawn/SupportedFeatures.kt",
     "java/android/dawn/SupportedLimits.kt",
     "java/android/dawn/SupportedWGSLLanguageFeatures.kt",
diff --git a/tools/android/webgpu/src/test/java/android/dawn/MappedNamedConstantsTest.kt b/tools/android/webgpu/src/test/java/android/dawn/MappedNamedConstantsTest.kt
index af343d2..8be833a 100644
--- a/tools/android/webgpu/src/test/java/android/dawn/MappedNamedConstantsTest.kt
+++ b/tools/android/webgpu/src/test/java/android/dawn/MappedNamedConstantsTest.kt
@@ -59,6 +59,7 @@
         StorageTextureAccess::class,
         StoreOp::class,
         SType::class,
+        SubgroupMatrixComponentType::class,
         SurfaceGetCurrentTextureStatus::class,
         TextureAspect::class,
         TextureDimension::class,