Vulkan: make PNextChainBuilder require pNext==nullptr

This will hopefully help catch issues early when people forget to set
pNext before creating the PNextChainBuilder.

Bug: dawn:1223
Change-Id: Ic6b9704aeaa20731e4f7de4d1ac0207d4110c720
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/71762
Reviewed-by: Loko Kung <lokokung@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn_native/vulkan/DeviceVk.cpp b/src/dawn_native/vulkan/DeviceVk.cpp
index 791818c..de7c8d4 100644
--- a/src/dawn_native/vulkan/DeviceVk.cpp
+++ b/src/dawn_native/vulkan/DeviceVk.cpp
@@ -320,6 +320,7 @@
         // if HasExt(DeviceExt::GetPhysicalDeviceProperties2) is true.
         VkPhysicalDeviceFeatures2 features2 = {};
         features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
+        features2.pNext = nullptr;
         PNextChainBuilder featuresChain(&features2);
 
         // Required for core WebGPU features.
diff --git a/src/dawn_native/vulkan/UtilsVulkan.h b/src/dawn_native/vulkan/UtilsVulkan.h
index 53b6d41..7b7ead5 100644
--- a/src/dawn_native/vulkan/UtilsVulkan.h
+++ b/src/dawn_native/vulkan/UtilsVulkan.h
@@ -30,16 +30,14 @@
 
     // A Helper type used to build a pNext chain of extension structs.
     // Usage is:
-    //   1) Create instance, passing the address of the first struct in the
-    //      chain. This will parse the existing |pNext| chain in it to find
-    //      its tail.
+    //   1) Create instance, passing the address of the first struct in the chain. This requires
+    //      pNext to be nullptr. If you already have a chain you need to pass a pointer to the tail
+    //      of it.
     //
-    //   2) Call Add(&vk_struct) every time a new struct needs to be appended
-    //      to the chain.
+    //   2) Call Add(&vk_struct) every time a new struct needs to be appended to the chain.
     //
-    //   3) Alternatively, call Add(&vk_struct, VK_STRUCTURE_TYPE_XXX) to
-    //      initialize the struct with a given VkStructureType value while
-    //      appending it to the chain.
+    //   3) Alternatively, call Add(&vk_struct, VK_STRUCTURE_TYPE_XXX) to initialize the struct
+    //      with a given VkStructureType value while appending it to the chain.
     //
     // Examples:
     //     VkPhysicalFeatures2 features2 = {
@@ -61,10 +59,7 @@
         template <typename VK_STRUCT_TYPE>
         explicit PNextChainBuilder(VK_STRUCT_TYPE* head)
             : mCurrent(reinterpret_cast<VkBaseOutStructure*>(head)) {
-            // Find the end of the current chain.
-            while (mCurrent->pNext != nullptr) {
-                mCurrent = mCurrent->pNext;
-            }
+            ASSERT(head->pNext == nullptr);
         }
 
         // Add one item to the chain. |vk_struct| must be a Vulkan structure
diff --git a/src/dawn_native/vulkan/VulkanInfo.cpp b/src/dawn_native/vulkan/VulkanInfo.cpp
index a053df1..4b0159f 100644
--- a/src/dawn_native/vulkan/VulkanInfo.cpp
+++ b/src/dawn_native/vulkan/VulkanInfo.cpp
@@ -219,10 +219,12 @@
         // because these extensions (transitively) depend on it in `EnsureDependencies`
         VkPhysicalDeviceFeatures2 features2 = {};
         features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
+        features2.pNext = nullptr;
         PNextChainBuilder featuresChain(&features2);
 
         VkPhysicalDeviceProperties2 properties2 = {};
         properties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
+        features2.pNext = nullptr;
         PNextChainBuilder propertiesChain(&properties2);
 
         if (info.extensions[DeviceExt::ShaderFloat16Int8]) {