[dawn][native] Add tests for reflection of DynamicArrayKind::Undefined.

This could not previously be written because there was no way to use a
dynamic binding array in shaders without a type. arrayLength now allows
that so write the relevant tests.

Bug: 435317394
Change-Id: Ib9a33faf08c1fd372b23447089fe32be10898c2e
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/259796
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn/native/PipelineLayout.cpp b/src/dawn/native/PipelineLayout.cpp
index 739efb8..23a4ab8 100644
--- a/src/dawn/native/PipelineLayout.cpp
+++ b/src/dawn/native/PipelineLayout.cpp
@@ -430,7 +430,8 @@
             if (dynamicArrays[group]->kind == wgpu::DynamicBindingKind::Undefined) {
                 dynamicArrays[group]->kind = array.kind;
             } else {
-                DAWN_INVALID_IF(dynamicArrays[group]->kind != array.kind,
+                DAWN_INVALID_IF(array.kind != wgpu::DynamicBindingKind::Undefined &&
+                                    dynamicArrays[group]->kind != array.kind,
                                 "Dynamic array kind doesn't match for @group(%u) between shader "
                                 "stages (%s vs. %s).",
                                 group, dynamicArrays[group]->kind, array.kind);
diff --git a/src/dawn/tests/unittests/validation/DynamicBindingArrayValidationTests.cpp b/src/dawn/tests/unittests/validation/DynamicBindingArrayValidationTests.cpp
index 6cbff07..e031f4c 100644
--- a/src/dawn/tests/unittests/validation/DynamicBindingArrayValidationTests.cpp
+++ b/src/dawn/tests/unittests/validation/DynamicBindingArrayValidationTests.cpp
@@ -902,17 +902,39 @@
     )"));
 }
 
+// Test that a shader using only arrayLength on the dynamic binding array is compatible with any
+// DynamicBindingKind.
+TEST_F(DynamicBindingArrayTests, DynamicArrayKindWithoutTypeInfoValidWithAllLayouts) {
+    wgpu::ComputePipelineDescriptor csDesc;
+    csDesc.compute.module = utils::CreateShaderModule(device, R"(
+        enable chromium_experimental_dynamic_binding;
+        @group(0) @binding(0) var a : resource_binding;
+
+        @compute @workgroup_size(1) fn main() {
+            _ = arrayLength(a);
+        }
+    )");
+
+    // Check that it is compatible with DynamicBindingKind::SampledTexture.
+    {
+        wgpu::BindGroupLayout bgl = MakeBindGroupLayout(wgpu::DynamicBindingKind::SampledTexture);
+        csDesc.layout = utils::MakeBasicPipelineLayout(device, &bgl);
+        device.CreateComputePipeline(&csDesc);
+    }
+
+    // TODO(https://crbug.com/435317394): Add tests with additional DynamicBindingKind.
+}
+
 // TODO(https://crbug.com/435317394): Add tests for the DynamicArrayKind. It is not possible to do
 // it at the moment because we cannot reflect DynamicArrayKind::Undefined (would require referencing
 // but not indexing the array) or any value that's not DynamicArrayKind::SampledTexture (no support
 // in Dawn or Tint for other cases). Tests to add after that are:
 //  - The kind in the layout must match the deduced kind for the shader.
 //     - Case with a resource_binding
-//  - A shader only referencing but not accessed with a resource_binding is valid to use with any
-//    DynamicArrayKind in the layout.
 //  - An error is produced at shader module compilation time if it uses the same resource_binding
 //    with different DynamicArrayKinds.
 //
+
 // Test that BGL defaulting works with dynamic binding arrays.
 TEST_F(DynamicBindingArrayTests, GetBGLSuccess) {
     wgpu::ComputePipelineDescriptor csDesc;
@@ -1134,13 +1156,100 @@
     }
 }
 
+// Test that defaulting the layout when no type information is given for the dynamic binding array
+// is an error.
+TEST_F(DynamicBindingArrayTests, DefaultedDynamicArrayKindMustNotBeUndefined) {
+    wgpu::ComputePipelineDescriptor csDesc;
+    csDesc.compute.module = utils::CreateShaderModule(device, R"(
+        enable chromium_experimental_dynamic_binding;
+        @group(0) @binding(0) var a : resource_binding;
+
+        @compute @workgroup_size(1) fn main() {
+            _ = arrayLength(a);
+        }
+    )");
+
+    // Control case, explicitly giving a layout works
+    wgpu::BindGroupLayout bgl = MakeBindGroupLayout(wgpu::DynamicBindingKind::SampledTexture);
+    csDesc.layout = utils::MakeBasicPipelineLayout(device, &bgl);
+    device.CreateComputePipeline(&csDesc);
+
+    // Error case, defaulting the layout is not possible.
+    csDesc.layout = nullptr;
+    ASSERT_DEVICE_ERROR(device.CreateComputePipeline(&csDesc));
+}
+
+// Test merging of DynamicBindingKind between VS and FS (FS typed case)
+TEST_F(DynamicBindingArrayTests, MergingUnknowVSDynamicArrayKindInFS) {
+    wgpu::ShaderModule module = utils::CreateShaderModule(device, R"(
+        enable chromium_experimental_dynamic_binding;
+
+        @group(0) @binding(0) var untyped : resource_binding;
+        @vertex fn vs() -> @builtin(position) vec4f {
+            _ = arrayLength(untyped);
+            return vec4f();
+        }
+
+        @group(0) @binding(0) var typed : resource_binding;
+        @fragment fn fs() -> @location(0) vec4f {
+            _ = hasBinding<texture_2d<f32>>(typed, 42);
+            return vec4f();
+        }
+    )");
+
+    utils::ComboRenderPipelineDescriptor pDesc;
+    pDesc.layout = nullptr;
+    pDesc.vertex.module = module;
+    pDesc.cFragment.module = module;
+    wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&pDesc);
+
+    // Check that this is a DynamicBindingKind::SampledTexture dynamic binding array.
+    wgpu::TextureDescriptor tDesc = {
+        .usage = wgpu::TextureUsage::TextureBinding,
+        .size = {1, 1},
+        .format = wgpu::TextureFormat::RGBA8Unorm,
+    };
+    wgpu::Texture tex = device.CreateTexture(&tDesc);
+    MakeBindGroup(pipeline.GetBindGroupLayout(0), 1, {{0, tex.CreateView()}});
+}
+
+// Test merging of DynamicBindingKind between VS and FS (VS typed case)
+TEST_F(DynamicBindingArrayTests, MergingUnknowFSDynamicArrayKindInVS) {
+    wgpu::ShaderModule module = utils::CreateShaderModule(device, R"(
+        enable chromium_experimental_dynamic_binding;
+
+        @group(0) @binding(0) var typed : resource_binding;
+        @vertex fn vs() -> @builtin(position) vec4f {
+            _ = hasBinding<texture_2d<f32>>(typed, 42);
+            return vec4f();
+        }
+
+        @group(0) @binding(0) var untyped : resource_binding;
+        @fragment fn fs() -> @location(0) vec4f {
+            _ = arrayLength(untyped);
+            return vec4f();
+        }
+    )");
+
+    utils::ComboRenderPipelineDescriptor pDesc;
+    pDesc.layout = nullptr;
+    pDesc.vertex.module = module;
+    pDesc.cFragment.module = module;
+    wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&pDesc);
+
+    // Check that this is a DynamicBindingKind::SampledTexture dynamic binding array.
+    wgpu::TextureDescriptor tDesc = {
+        .usage = wgpu::TextureUsage::TextureBinding,
+        .size = {1, 1},
+        .format = wgpu::TextureFormat::RGBA8Unorm,
+    };
+    wgpu::Texture tex = device.CreateTexture(&tDesc);
+    MakeBindGroup(pipeline.GetBindGroupLayout(0), 1, {{0, tex.CreateView()}});
+}
+
 // TODO(https://crbug.com/435317394): Add tests for the DynamicArrayKind defaulting / merging
 // between stages. Tests to add are:
 //  - Using two incompatible kinds between stages produces an error.
-//  - Using DynamicArrayKind::Undefined in a stage and not the other makes the BGL default to the
-//    non-Unknown DynamicArrayKind. (test both VS-FS and FS-VS directions to be safe).
-//  - Test what happens when only DynamicArrayKind::Undefined is used in the defaulted layout. Is
-//    that even valid?
 
 // Test that pinning / unpinning is valid for a simple case. This is a control for the test that
 // errors are produced when the feature is not enabled.