Dawn native/wire: Add experimental immediate data limits

This CL add the experimental immediate data limits by introducing a new
structure DawnExperimentalImmediateDataLimits. Insert it in the
SupportedLimits chained list.
The structure can be used for querying adapter or device limits. The
result would be WGPU_LIMIT_U32_UNDEFINED if AllowUnsafeAPI is not
enabled.

Bug: 366291600
Change-Id: I898712213827b0d415e88179c37d37ce0767c99d
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/206974
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Jiawei Shao <jiawei.shao@intel.com>
Commit-Queue: Shaobo Yan <shaobo.yan@intel.com>
diff --git a/src/dawn/dawn.json b/src/dawn/dawn.json
index 063eefa..32e4053 100644
--- a/src/dawn/dawn.json
+++ b/src/dawn/dawn.json
@@ -1984,6 +1984,15 @@
             {"name": "max subgroup size", "type": "uint32_t", "default": "WGPU_LIMIT_U32_UNDEFINED"}
         ]
     },
+    "dawn experimental immediate data limits": {
+        "category": "structure",
+        "chained": "out",
+        "chain roots": ["supported limits"],
+        "tags": ["dawn"],
+        "members": [
+            {"name": "max immediate data range byte size", "type": "uint32_t", "default": "WGPU_LIMIT_U32_UNDEFINED"}
+        ]
+    },
     "required limits": {
         "category": "structure",
         "extensible": "in",
@@ -2659,7 +2668,8 @@
             {"value": 53, "name": "dawn load resolve texture", "tags": ["dawn"]},
             {"value": 54, "name": "dawn partial load resolve texture", "tags": ["dawn"]},
             {"value": 55, "name": "multi draw indirect", "tags": ["dawn"]},
-            {"value": 56, "name": "clip distances", "tags": ["dawn"]}
+            {"value": 56, "name": "clip distances", "tags": ["dawn"]},
+            {"value": 57, "name": "chromium experimental immediate data", "tags": ["dawn"]}
         ]
     },
     "filter mode": {
@@ -4337,7 +4347,8 @@
             {"value": 55, "name": "static sampler binding layout", "tags": ["dawn"]},
             {"value": 56, "name": "y cb cr vk descriptor", "tags": ["dawn"]},
             {"value": 57, "name": "shared texture memory a hardware buffer properties", "tags": ["dawn", "native"]},
-            {"value": 58, "name": "a hardware buffer properties", "tags": ["dawn", "native"]}
+            {"value": 58, "name": "a hardware buffer properties", "tags": ["dawn", "native"]},
+            {"value": 59, "name": "dawn experimental immediate data limits", "tags": ["dawn"]}
 
         ]
     },
diff --git a/src/dawn/native/Adapter.cpp b/src/dawn/native/Adapter.cpp
index ca16d9b..f821e52 100644
--- a/src/dawn/native/Adapter.cpp
+++ b/src/dawn/native/Adapter.cpp
@@ -108,6 +108,7 @@
 
     // TODO(349125474): Deprecate DawnExperimentalSubgroupLimits.
     if (auto* subgroupLimits = unpacked.Get<DawnExperimentalSubgroupLimits>()) {
+        wgpu::ChainedStructOut* originalChain = subgroupLimits->nextInChain;
         if (!mSupportedFeatures.IsEnabled(wgpu::FeatureName::Subgroups)) {
             // If subgroups features are not supported, return the default-initialized
             // DawnExperimentalSubgroupLimits object, where minSubgroupSize and
@@ -117,6 +118,26 @@
             // If adapter supports subgroups features, always return the valid subgroup limits.
             *subgroupLimits = mPhysicalDevice->GetLimits().experimentalSubgroupLimits;
         }
+
+        // Recover origin chain.
+        subgroupLimits->nextInChain = originalChain;
+    }
+
+    if (auto* immediateDataLimits = unpacked.Get<DawnExperimentalImmediateDataLimits>()) {
+        wgpu::ChainedStructOut* originalChain = immediateDataLimits->nextInChain;
+        if (!mSupportedFeatures.IsEnabled(wgpu::FeatureName::ChromiumExperimentalImmediateData)) {
+            // If immediate data features are not supported, return the default-initialized
+            // DawnExperimentalImmediateDataLimits object, where maxImmediateDataByteSize is
+            // WGPU_LIMIT_U32_UNDEFINED.
+            *immediateDataLimits = DawnExperimentalImmediateDataLimits{};
+        } else {
+            // If adapter supports immediate data features, always return the valid immediate data
+            // limits.
+            *immediateDataLimits = mPhysicalDevice->GetLimits().experimentalImmediateDataLimits;
+        }
+
+        // Recover origin chain.
+        immediateDataLimits->nextInChain = originalChain;
     }
 
     return wgpu::Status::Success;
diff --git a/src/dawn/native/Device.cpp b/src/dawn/native/Device.cpp
index 7934197..0a6cbba 100644
--- a/src/dawn/native/Device.cpp
+++ b/src/dawn/native/Device.cpp
@@ -428,6 +428,10 @@
     mLimits.experimentalSubgroupLimits =
         GetPhysicalDevice()->GetLimits().experimentalSubgroupLimits;
 
+    // Get experimentalImmediateDataRangeByteSizeLimit from physical device
+    mLimits.experimentalImmediateDataLimits =
+        GetPhysicalDevice()->GetLimits().experimentalImmediateDataLimits;
+
     mFormatTable = BuildFormatTable(this);
 
     if (descriptor->label != nullptr && strlen(descriptor->label) != 0) {
@@ -1986,6 +1990,7 @@
     limits->limits = mLimits.v1;
 
     if (auto* subgroupLimits = unpacked.Get<DawnExperimentalSubgroupLimits>()) {
+        wgpu::ChainedStructOut* originalChain = subgroupLimits->nextInChain;
         // TODO(349125474): Remove deprecated ChromiumExperimentalSubgroups.
         if (!(HasFeature(Feature::Subgroups) ||
               HasFeature(Feature::ChromiumExperimentalSubgroups))) {
@@ -1996,6 +2001,24 @@
         } else {
             *subgroupLimits = mLimits.experimentalSubgroupLimits;
         }
+
+        // Recover origin chain.
+        subgroupLimits->nextInChain = originalChain;
+    }
+
+    if (auto* immediateDataLimits = unpacked.Get<DawnExperimentalImmediateDataLimits>()) {
+        wgpu::ChainedStructOut* originalChain = immediateDataLimits->nextInChain;
+        if (!HasFeature(Feature::ChromiumExperimentalImmediateData)) {
+            // If immediate data feature is not enabled, return the default-initialized
+            // DawnExperimentalImmediateDataLimits object, where maxImmediateDataRangeByteSize and
+            // are WGPU_LIMIT_U32_UNDEFINED.
+            *immediateDataLimits = DawnExperimentalImmediateDataLimits{};
+        } else {
+            *immediateDataLimits = mLimits.experimentalImmediateDataLimits;
+        }
+
+        // Recover origin chain.
+        immediateDataLimits->nextInChain = originalChain;
     }
 
     return wgpu::Status::Success;
diff --git a/src/dawn/native/Features.cpp b/src/dawn/native/Features.cpp
index 81ce2ac..b2e4905 100644
--- a/src/dawn/native/Features.cpp
+++ b/src/dawn/native/Features.cpp
@@ -396,6 +396,10 @@
     {Feature::ClipDistances,
      {"Support the \"enable clip_distances;\" directive in WGSL.",
       "https://gpuweb.github.io/gpuweb/#dom-gpufeaturename-clip-distances",
+      FeatureInfo::FeatureState::Experimental}},
+    {Feature::ChromiumExperimentalImmediateData,
+     {"Support the \"enable chromium_experimental_immediate_data;\" directive in WGSL.",
+      "https://github.com/gpuweb/gpuweb/blob/main/proposals/push-constants.md",
       FeatureInfo::FeatureState::Experimental}}};
 
 }  // anonymous namespace
diff --git a/src/dawn/native/Limits.h b/src/dawn/native/Limits.h
index a86cd43..7056324 100644
--- a/src/dawn/native/Limits.h
+++ b/src/dawn/native/Limits.h
@@ -38,6 +38,7 @@
 struct CombinedLimits {
     Limits v1;
     DawnExperimentalSubgroupLimits experimentalSubgroupLimits;
+    DawnExperimentalImmediateDataLimits experimentalImmediateDataLimits;
 };
 
 // Populate |limits| with the default limits.
diff --git a/src/dawn/native/null/DeviceNull.cpp b/src/dawn/native/null/DeviceNull.cpp
index 7949b7c..6953c4c 100644
--- a/src/dawn/native/null/DeviceNull.cpp
+++ b/src/dawn/native/null/DeviceNull.cpp
@@ -92,6 +92,7 @@
     // Set the subgroups limit, as DeviceNull should support subgroups feature.
     limits->experimentalSubgroupLimits.minSubgroupSize = 4;
     limits->experimentalSubgroupLimits.maxSubgroupSize = 128;
+    limits->experimentalImmediateDataLimits.maxImmediateDataRangeByteSize = 16;
     return {};
 }
 
diff --git a/src/dawn/node/binding/Converter.cpp b/src/dawn/node/binding/Converter.cpp
index 702399f..646ec1c 100644
--- a/src/dawn/node/binding/Converter.cpp
+++ b/src/dawn/node/binding/Converter.cpp
@@ -1499,6 +1499,9 @@
         case interop::GPUFeatureName::kChromiumExperimentalSubgroupUniformControlFlow:
             out = wgpu::FeatureName::ChromiumExperimentalSubgroupUniformControlFlow;
             return true;
+        case interop::GPUFeatureName::kChromiumExperimentalImmediateData:
+            out = wgpu::FeatureName::ChromiumExperimentalImmediateData;
+            return true;
         case interop::GPUFeatureName::kTextureCompressionBcSliced3D:
         case interop::GPUFeatureName::kClipDistances:
             return false;
@@ -1532,6 +1535,7 @@
         CASE(MultiDrawIndirect, kMultiDrawIndirect);
         CASE(DualSourceBlending, kDualSourceBlending);
         CASE(ClipDistances, kClipDistances);
+        CASE(ChromiumExperimentalImmediateData, kChromiumExperimentalImmediateData);
 
 #undef CASE
 
diff --git a/src/dawn/node/binding/GPUAdapter.cpp b/src/dawn/node/binding/GPUAdapter.cpp
index 75b35ac..3bd9779 100644
--- a/src/dawn/node/binding/GPUAdapter.cpp
+++ b/src/dawn/node/binding/GPUAdapter.cpp
@@ -101,14 +101,27 @@
 interop::Interface<interop::GPUSupportedLimits> GPUAdapter::getLimits(Napi::Env env) {
     wgpu::SupportedLimits limits{};
     wgpu::DawnExperimentalSubgroupLimits subgroupLimits{};
+    wgpu::DawnExperimentalImmediateDataLimits immediateDataLimits{};
 
     wgpu::Adapter wgpuAdapter = adapter_.Get();
 
+    auto InsertInChain = [&](wgpu::ChainedStructOut* node) {
+        node->nextInChain = limits.nextInChain;
+        limits.nextInChain = node;
+    };
+
+    wgpu::ChainedStructOut** limitsListTail = &limits.nextInChain;
     // Query the subgroup limits only if subgroups feature is available on the adapter.
     // TODO(349125474): Remove deprecated ChromiumExperimentalSubgroups.
     if (wgpuAdapter.HasFeature(FeatureName::Subgroups) ||
         wgpuAdapter.HasFeature(FeatureName::ChromiumExperimentalSubgroups)) {
-        limits.nextInChain = &subgroupLimits;
+        InsertInChain(&subgroupLimits);
+    }
+
+    // Query the immediate data limits only if ChromiumExperimentalImmediateData feature
+    // is available on adapter.
+    if (wgpuAdapter.HasFeature(FeatureName::ChromiumExperimentalImmediateData)) {
+        InsertInChain(&immediateDataLimits);
     }
 
     if (!wgpuAdapter.GetLimits(&limits)) {
diff --git a/src/dawn/node/binding/GPUDevice.cpp b/src/dawn/node/binding/GPUDevice.cpp
index d024f83..55591b2 100644
--- a/src/dawn/node/binding/GPUDevice.cpp
+++ b/src/dawn/node/binding/GPUDevice.cpp
@@ -185,12 +185,24 @@
 interop::Interface<interop::GPUSupportedLimits> GPUDevice::getLimits(Napi::Env env) {
     wgpu::SupportedLimits limits{};
     wgpu::DawnExperimentalSubgroupLimits subgroupLimits{};
+    wgpu::DawnExperimentalImmediateDataLimits immediateDataLimits{};
+
+    auto InsertInChain = [&](wgpu::ChainedStructOut* node) {
+        node->nextInChain = limits.nextInChain;
+        limits.nextInChain = node;
+    };
 
     // Query the subgroup limits only if subgroups feature is enabled on the device.
     // TODO(349125474): Remove deprecated ChromiumExperimentalSubgroups.
     if (device_.HasFeature(wgpu::FeatureName::Subgroups) ||
         device_.HasFeature(wgpu::FeatureName::ChromiumExperimentalSubgroups)) {
-        limits.nextInChain = &subgroupLimits;
+        InsertInChain(&subgroupLimits);
+    }
+
+    // Query the immediate data limits only if ChromiumExperimentalImmediateData feature
+    // is available on device.
+    if (device_.HasFeature(FeatureName::ChromiumExperimentalImmediateData)) {
+        InsertInChain(&subgroupLimits);
     }
 
     if (!device_.GetLimits(&limits)) {
diff --git a/src/dawn/node/interop/DawnExtensions.idl b/src/dawn/node/interop/DawnExtensions.idl
index 4e7e67d..583f204 100644
--- a/src/dawn/node/interop/DawnExtensions.idl
+++ b/src/dawn/node/interop/DawnExtensions.idl
@@ -35,6 +35,7 @@
     "subgroups",
     "subgroups-f16",
     "multi-draw-indirect",
+    "chromium-experimental-immediate-data",
 };
 
 dictionary GPURequestAdapterOptions {
diff --git a/src/dawn/wire/SupportedFeatures.cpp b/src/dawn/wire/SupportedFeatures.cpp
index c914198..9844b05 100644
--- a/src/dawn/wire/SupportedFeatures.cpp
+++ b/src/dawn/wire/SupportedFeatures.cpp
@@ -113,6 +113,7 @@
         case WGPUFeatureName_Subgroups:
         case WGPUFeatureName_SubgroupsF16:
         case WGPUFeatureName_ClipDistances:
+        case WGPUFeatureName_ChromiumExperimentalImmediateData:
             return true;
     }
 
diff --git a/src/dawn/wire/client/LimitsAndFeatures.cpp b/src/dawn/wire/client/LimitsAndFeatures.cpp
index 74454a0..612890a 100644
--- a/src/dawn/wire/client/LimitsAndFeatures.cpp
+++ b/src/dawn/wire/client/LimitsAndFeatures.cpp
@@ -53,6 +53,13 @@
                 *experimentalSubgroupLimits = mExperimentalSubgroupLimits;
                 break;
             }
+            case (WGPUSType_DawnExperimentalImmediateDataLimits): {
+                auto* experimentalImmediateDataLimits =
+                    reinterpret_cast<WGPUDawnExperimentalImmediateDataLimits*>(chain);
+                // This assignment break the next field of WGPUChainedStructOut head.
+                *experimentalImmediateDataLimits = mExperimentalImmediateDataLimits;
+                break;
+            }
             default:
                 // Fail if unknown sType found.
                 return WGPUStatus_Error;
@@ -91,6 +98,13 @@
                 mExperimentalSubgroupLimits.chain.next = nullptr;
                 break;
             }
+            case (WGPUSType_DawnExperimentalImmediateDataLimits): {
+                auto* experimentalImmediateDataLimits =
+                    reinterpret_cast<WGPUDawnExperimentalImmediateDataLimits*>(chain);
+                mExperimentalImmediateDataLimits = *experimentalImmediateDataLimits;
+                mExperimentalImmediateDataLimits.chain.next = nullptr;
+                break;
+            }
             default:
                 DAWN_UNREACHABLE();
         }
diff --git a/src/dawn/wire/client/LimitsAndFeatures.h b/src/dawn/wire/client/LimitsAndFeatures.h
index b29ffd0..5846a58 100644
--- a/src/dawn/wire/client/LimitsAndFeatures.h
+++ b/src/dawn/wire/client/LimitsAndFeatures.h
@@ -49,6 +49,7 @@
   private:
     WGPUSupportedLimits mLimits;
     WGPUDawnExperimentalSubgroupLimits mExperimentalSubgroupLimits;
+    WGPUDawnExperimentalImmediateDataLimits mExperimentalImmediateDataLimits;
     absl::flat_hash_set<WGPUFeatureName> mFeatures;
 };
 
diff --git a/src/dawn/wire/server/ServerAdapter.cpp b/src/dawn/wire/server/ServerAdapter.cpp
index 6f9cab2..1267930 100644
--- a/src/dawn/wire/server/ServerAdapter.cpp
+++ b/src/dawn/wire/server/ServerAdapter.cpp
@@ -122,11 +122,20 @@
     cmd.featuresCount = features.size();
     cmd.features = features.data();
 
+    // Query and report the adapter limits, including DawnExperimentalSubgroupLimits and
+    // DawnExperimentalImmediateDataLimits. Reporting to client.
     WGPUSupportedLimits limits = {};
-    // Also query the DawnExperimentalSubgroupLimits and report to client.
+
+    // Chained DawnExperimentalSubgroupLimits.
     WGPUDawnExperimentalSubgroupLimits experimentalSubgroupLimits = {};
     experimentalSubgroupLimits.chain.sType = WGPUSType_DawnExperimentalSubgroupLimits;
     limits.nextInChain = &experimentalSubgroupLimits.chain;
+
+    // Chained DawnExperimentalImmediateDataLimits.
+    WGPUDawnExperimentalImmediateDataLimits experimentalImmediateDataLimits = {};
+    experimentalImmediateDataLimits.chain.sType = WGPUSType_DawnExperimentalImmediateDataLimits;
+    experimentalSubgroupLimits.chain.next = &experimentalImmediateDataLimits.chain;
+
     mProcs.deviceGetLimits(device, &limits);
     cmd.limits = &limits;
 
diff --git a/src/dawn/wire/server/ServerInstance.cpp b/src/dawn/wire/server/ServerInstance.cpp
index 65c9b85..ca87d8c 100644
--- a/src/dawn/wire/server/ServerInstance.cpp
+++ b/src/dawn/wire/server/ServerInstance.cpp
@@ -129,13 +129,19 @@
     mProcs.adapterGetInfo(adapter, &info);
     cmd.info = &info;
 
-    // Query and report the adapter limits, including DawnExperimentalSubgroupLimits.
+    // Query and report the adapter limits, including DawnExperimentalSubgroupLimits and
+    // DawnExperimentalImmediateDataLimits.
     WGPUSupportedLimits limits = {};
 
     WGPUDawnExperimentalSubgroupLimits experimentalSubgroupLimits = {};
     experimentalSubgroupLimits.chain.sType = WGPUSType_DawnExperimentalSubgroupLimits;
     limits.nextInChain = &experimentalSubgroupLimits.chain;
 
+    // Chained DawnExperimentalImmediateDataLimits.
+    WGPUDawnExperimentalImmediateDataLimits experimentalImmediateDataLimits = {};
+    experimentalImmediateDataLimits.chain.sType = WGPUSType_DawnExperimentalImmediateDataLimits;
+    experimentalSubgroupLimits.chain.next = &experimentalImmediateDataLimits.chain;
+
     mProcs.adapterGetLimits(adapter, &limits);
     cmd.limits = &limits;