Construct VertexInputDescriptor, in order to match web idl

BUG=dawn:107

Change-Id: Ic219fb98a88a7ac597fbdc592f604f27b76d756b
Reviewed-on: https://dawn-review.googlesource.com/c/4721
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Commit-Queue: Yunchao He <yunchao.he@intel.com>
diff --git a/dawn.json b/dawn.json
index db257ee..89e4017 100644
--- a/dawn.json
+++ b/dawn.json
@@ -598,6 +598,15 @@
             {"name": "format", "type": "vertex format"}
         ]
     },
+    "vertex input descriptor": {
+        "category": "structure",
+        "extensible": false,
+        "members": [
+            {"name": "input slot", "type": "uint32_t"},
+            {"name": "stride", "type": "uint32_t"},
+            {"name": "step mode", "type": "input step mode"}
+        ]
+    },
     "input state": {
         "category": "object"
     },
@@ -617,9 +626,7 @@
             {
                 "name": "set input",
                 "args": [
-                    {"name": "binding slot", "type": "uint32_t"},
-                    {"name": "stride", "type": "uint32_t"},
-                    {"name": "step mode", "type": "input step mode"}
+                    {"name": "input", "type": "vertex input descriptor", "annotation": "const*"}
                 ]
             }
         ]
diff --git a/examples/ComputeBoids.cpp b/examples/ComputeBoids.cpp
index fd5b906..4fd1fa1 100644
--- a/examples/ComputeBoids.cpp
+++ b/examples/ComputeBoids.cpp
@@ -126,18 +126,28 @@
     attribute2.offset = offsetof(Particle, vel);
     attribute2.format = dawn::VertexFormat::FloatR32G32;
 
+    dawn::VertexInputDescriptor input1;
+    input1.inputSlot = 0;
+    input1.stride = sizeof(Particle);
+    input1.stepMode = dawn::InputStepMode::Instance;
+
     dawn::VertexAttributeDescriptor attribute3;
     attribute3.shaderLocation = 2;
     attribute3.inputSlot = 1;
     attribute3.offset = 0;
     attribute3.format = dawn::VertexFormat::FloatR32G32;
 
+    dawn::VertexInputDescriptor input2;
+    input2.inputSlot = 1;
+    input2.stride = sizeof(glm::vec2);
+    input2.stepMode = dawn::InputStepMode::Vertex;
+
     dawn::InputState inputState = device.CreateInputStateBuilder()
                                       .SetAttribute(&attribute1)
                                       .SetAttribute(&attribute2)
-                                      .SetInput(0, sizeof(Particle), dawn::InputStepMode::Instance)
+                                      .SetInput(&input1)
                                       .SetAttribute(&attribute3)
-                                      .SetInput(1, sizeof(glm::vec2), dawn::InputStepMode::Vertex)
+                                      .SetInput(&input2)
                                       .GetResult();
 
     depthStencilView = CreateDefaultDepthStencilView(device);
diff --git a/examples/CppHelloTriangle.cpp b/examples/CppHelloTriangle.cpp
index 3719199..0f5d790 100644
--- a/examples/CppHelloTriangle.cpp
+++ b/examples/CppHelloTriangle.cpp
@@ -116,10 +116,14 @@
     attribute.inputSlot = 0;
     attribute.offset = 0;
     attribute.format = dawn::VertexFormat::FloatR32G32B32A32;
-    auto inputState = device.CreateInputStateBuilder()
-                          .SetAttribute(&attribute)
-                          .SetInput(0, 4 * sizeof(float), dawn::InputStepMode::Vertex)
-                          .GetResult();
+
+    dawn::VertexInputDescriptor input;
+    input.inputSlot = 0;
+    input.stride = 4 * sizeof(float);
+    input.stepMode = dawn::InputStepMode::Vertex;
+
+    auto inputState =
+        device.CreateInputStateBuilder().SetAttribute(&attribute).SetInput(&input).GetResult();
 
     auto bgl = utils::MakeBindGroupLayout(
         device, {
diff --git a/examples/CubeReflection.cpp b/examples/CubeReflection.cpp
index ae91519..f9fc5a6 100644
--- a/examples/CubeReflection.cpp
+++ b/examples/CubeReflection.cpp
@@ -168,10 +168,15 @@
     attribute2.offset = 3 * sizeof(float);
     attribute2.format = dawn::VertexFormat::FloatR32G32B32;
 
+    dawn::VertexInputDescriptor input;
+    input.inputSlot = 0;
+    input.stride = 6 * sizeof(float);
+    input.stepMode = dawn::InputStepMode::Vertex;
+
     auto inputState = device.CreateInputStateBuilder()
                           .SetAttribute(&attribute1)
                           .SetAttribute(&attribute2)
-                          .SetInput(0, 6 * sizeof(float), dawn::InputStepMode::Vertex)
+                          .SetInput(&input)
                           .GetResult();
 
     auto bgl = utils::MakeBindGroupLayout(
diff --git a/examples/glTFViewer/glTFViewer.cpp b/examples/glTFViewer/glTFViewer.cpp
index d436cf4..d36358b 100644
--- a/examples/glTFViewer/glTFViewer.cpp
+++ b/examples/glTFViewer/glTFViewer.cpp
@@ -250,23 +250,32 @@
             dawn::VertexAttributeDescriptor attribute;
             attribute.offset = 0;
             attribute.format = format;
+            dawn::VertexInputDescriptor input;
+            input.stepMode = dawn::InputStepMode::Vertex;
+
             if (iParameter.semantic == "POSITION") {
                 attribute.shaderLocation = 0;
                 attribute.inputSlot = 0;
+                input.inputSlot = 0;
+                input.stride = static_cast<uint32_t>(stridePos);
                 builder.SetAttribute(&attribute);
-                builder.SetInput(0, static_cast<uint32_t>(stridePos), dawn::InputStepMode::Vertex);
+                builder.SetInput(&input);
                 slotsSet.set(0);
             } else if (iParameter.semantic == "NORMAL") {
                 attribute.shaderLocation = 1;
                 attribute.inputSlot = 1;
+                input.inputSlot = 1;
+                input.stride = static_cast<uint32_t>(strideNor);
                 builder.SetAttribute(&attribute);
-                builder.SetInput(1, static_cast<uint32_t>(strideNor), dawn::InputStepMode::Vertex);
+                builder.SetInput(&input);
                 slotsSet.set(1);
             } else if (iParameter.semantic == "TEXCOORD_0") {
                 attribute.shaderLocation = 2;
                 attribute.inputSlot = 2;
+                input.inputSlot = 2;
+                input.stride = static_cast<uint32_t>(strideTxc);
                 builder.SetAttribute(&attribute);
-                builder.SetInput(2, static_cast<uint32_t>(strideTxc), dawn::InputStepMode::Vertex);
+                builder.SetInput(&input);
                 slotsSet.set(2);
             } else {
                 fprintf(stderr, "unsupported technique attribute semantic %s\n", iParameter.semantic.c_str());
@@ -283,8 +292,13 @@
             attribute.inputSlot = i;
             attribute.format = dawn::VertexFormat::FloatR32G32B32A32;
 
+            dawn::VertexInputDescriptor input;
+            input.inputSlot = i;
+            input.stride = 0;
+            input.stepMode = dawn::InputStepMode::Vertex;
+
             builder.SetAttribute(&attribute);
-            builder.SetInput(i, 0, dawn::InputStepMode::Vertex);
+            builder.SetInput(&input);
         }
         auto inputState = builder.GetResult();
 
diff --git a/src/dawn_native/InputState.cpp b/src/dawn_native/InputState.cpp
index fb55b39..5272f0f 100644
--- a/src/dawn_native/InputState.cpp
+++ b/src/dawn_native/InputState.cpp
@@ -147,22 +147,20 @@
         info.format = attribute->format;
     }
 
-    void InputStateBuilder::SetInput(uint32_t bindingSlot,
-                                     uint32_t stride,
-                                     dawn::InputStepMode stepMode) {
-        if (bindingSlot >= kMaxVertexInputs) {
+    void InputStateBuilder::SetInput(const VertexInputDescriptor* input) {
+        if (input->inputSlot >= kMaxVertexInputs) {
             HandleError("Setting input out of bounds");
             return;
         }
-        if (mInputsSetMask[bindingSlot]) {
+        if (mInputsSetMask[input->inputSlot]) {
             HandleError("Setting already set input");
             return;
         }
 
-        mInputsSetMask.set(bindingSlot);
-        auto& info = mInputInfos[bindingSlot];
-        info.stride = stride;
-        info.stepMode = stepMode;
+        mInputsSetMask.set(input->inputSlot);
+        auto& info = mInputInfos[input->inputSlot];
+        info.stride = input->stride;
+        info.stepMode = input->stepMode;
     }
 
 }  // namespace dawn_native
diff --git a/src/dawn_native/InputState.h b/src/dawn_native/InputState.h
index a9ca43a..5d5300a 100644
--- a/src/dawn_native/InputState.h
+++ b/src/dawn_native/InputState.h
@@ -65,7 +65,7 @@
 
         // Dawn API
         void SetAttribute(const VertexAttributeDescriptor* attribute);
-        void SetInput(uint32_t bindingSlot, uint32_t stride, dawn::InputStepMode stepMode);
+        void SetInput(const VertexInputDescriptor* input);
 
       private:
         friend class InputStateBase;
diff --git a/src/tests/end2end/DrawIndexedTests.cpp b/src/tests/end2end/DrawIndexedTests.cpp
index b824b9a..a1bb77b 100644
--- a/src/tests/end2end/DrawIndexedTests.cpp
+++ b/src/tests/end2end/DrawIndexedTests.cpp
@@ -26,17 +26,21 @@
 
             renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
 
+            dawn::VertexInputDescriptor input;
+            input.inputSlot = 0;
+            input.stride = 4 * sizeof(float);
+            input.stepMode = dawn::InputStepMode::Vertex;
+
             dawn::VertexAttributeDescriptor attribute;
             attribute.shaderLocation = 0;
             attribute.inputSlot = 0;
             attribute.offset = 0;
             attribute.format = dawn::VertexFormat::FloatR32G32B32A32;
 
-            dawn::InputState inputState =
-                device.CreateInputStateBuilder()
-                    .SetInput(0, 4 * sizeof(float), dawn::InputStepMode::Vertex)
-                    .SetAttribute(&attribute)
-                    .GetResult();
+            dawn::InputState inputState = device.CreateInputStateBuilder()
+                                              .SetInput(&input)
+                                              .SetAttribute(&attribute)
+                                              .GetResult();
 
             dawn::ShaderModule vsModule = utils::CreateShaderModule(device, dawn::ShaderStage::Vertex, R"(
                 #version 450
diff --git a/src/tests/end2end/DrawTests.cpp b/src/tests/end2end/DrawTests.cpp
index 7f818dc..3af05e1 100644
--- a/src/tests/end2end/DrawTests.cpp
+++ b/src/tests/end2end/DrawTests.cpp
@@ -26,6 +26,11 @@
 
         renderPass = utils::CreateBasicRenderPass(device, kRTSize, kRTSize);
 
+        dawn::VertexInputDescriptor input;
+        input.inputSlot = 0;
+        input.stride = 4 * sizeof(float);
+        input.stepMode = dawn::InputStepMode::Vertex;
+
         dawn::VertexAttributeDescriptor attribute;
         attribute.shaderLocation = 0;
         attribute.inputSlot = 0;
@@ -33,10 +38,7 @@
         attribute.format = dawn::VertexFormat::FloatR32G32B32A32;
 
         dawn::InputState inputState =
-            device.CreateInputStateBuilder()
-                .SetInput(0, 4 * sizeof(float), dawn::InputStepMode::Vertex)
-                .SetAttribute(&attribute)
-                .GetResult();
+            device.CreateInputStateBuilder().SetInput(&input).SetAttribute(&attribute).GetResult();
 
         dawn::ShaderModule vsModule =
             utils::CreateShaderModule(device, dawn::ShaderStage::Vertex, R"(
diff --git a/src/tests/end2end/IndexFormatTests.cpp b/src/tests/end2end/IndexFormatTests.cpp
index 8e5fb10..a2690a9 100644
--- a/src/tests/end2end/IndexFormatTests.cpp
+++ b/src/tests/end2end/IndexFormatTests.cpp
@@ -31,17 +31,21 @@
         utils::BasicRenderPass renderPass;
 
         dawn::RenderPipeline MakeTestPipeline(dawn::IndexFormat format) {
+            dawn::VertexInputDescriptor input;
+            input.inputSlot = 0;
+            input.stride = 4 * sizeof(float);
+            input.stepMode = dawn::InputStepMode::Vertex;
+
             dawn::VertexAttributeDescriptor attribute;
             attribute.shaderLocation = 0;
             attribute.inputSlot = 0;
             attribute.offset = 0;
             attribute.format = dawn::VertexFormat::FloatR32G32B32A32;
 
-            dawn::InputState inputState =
-                device.CreateInputStateBuilder()
-                    .SetInput(0, 4 * sizeof(float), dawn::InputStepMode::Vertex)
-                    .SetAttribute(&attribute)
-                    .GetResult();
+            dawn::InputState inputState = device.CreateInputStateBuilder()
+                                              .SetInput(&input)
+                                              .SetAttribute(&attribute)
+                                              .GetResult();
 
             dawn::ShaderModule vsModule = utils::CreateShaderModule(device, dawn::ShaderStage::Vertex, R"(
                 #version 450
diff --git a/src/tests/end2end/InputStateTests.cpp b/src/tests/end2end/InputStateTests.cpp
index 73a2b61..39b4f7e 100644
--- a/src/tests/end2end/InputStateTests.cpp
+++ b/src/tests/end2end/InputStateTests.cpp
@@ -145,7 +145,11 @@
             dawn::InputStateBuilder builder = device.CreateInputStateBuilder();
 
             for (const auto& input : inputs) {
-                builder.SetInput(input.slot, input.stride, input.step);
+                dawn::VertexInputDescriptor descriptor;
+                descriptor.inputSlot = input.slot;
+                descriptor.stride = input.stride;
+                descriptor.stepMode = input.step;
+                builder.SetInput(&descriptor);
             }
 
             for (const auto& attribute : attributes) {
diff --git a/src/tests/end2end/PrimitiveTopologyTests.cpp b/src/tests/end2end/PrimitiveTopologyTests.cpp
index 193414e..50119ad 100644
--- a/src/tests/end2end/PrimitiveTopologyTests.cpp
+++ b/src/tests/end2end/PrimitiveTopologyTests.cpp
@@ -171,9 +171,14 @@
             attribute.offset = 0;
             attribute.format = dawn::VertexFormat::FloatR32G32B32A32;
 
+            dawn::VertexInputDescriptor input;
+            input.inputSlot = 0;
+            input.stride = 4 * sizeof(float);
+            input.stepMode = dawn::InputStepMode::Vertex;
+
             inputState = device.CreateInputStateBuilder()
                              .SetAttribute(&attribute)
-                             .SetInput(0, 4 * sizeof(float), dawn::InputStepMode::Vertex)
+                             .SetInput(&input)
                              .GetResult();
 
             vertexBuffer = utils::CreateBufferFromData(device, kVertices, sizeof(kVertices), dawn::BufferUsageBit::Vertex);
diff --git a/src/tests/unittests/validation/InputStateValidationTests.cpp b/src/tests/unittests/validation/InputStateValidationTests.cpp
index 07ac93a..e8967a8 100644
--- a/src/tests/unittests/validation/InputStateValidationTests.cpp
+++ b/src/tests/unittests/validation/InputStateValidationTests.cpp
@@ -17,6 +17,12 @@
 #include "utils/ComboRenderPipelineDescriptor.h"
 #include "utils/DawnHelpers.h"
 
+constexpr static dawn::VertexInputDescriptor kBaseInput = {
+    0,                            // inputSlot
+    0,                            // stride
+    dawn::InputStepMode::Vertex,  // stepMode
+};
+
 class InputStateTest : public ValidationTest {
     protected:
         void CreatePipeline(bool success, const dawn::InputState& inputState, std::string vertexSource) {
@@ -70,8 +76,13 @@
     attribute2.offset = sizeof(float);
     attribute2.format = dawn::VertexFormat::FloatR32;
 
+    dawn::VertexInputDescriptor input;
+    input.inputSlot = 0;
+    input.stride = 2 * sizeof(float);
+    input.stepMode = dawn::InputStepMode::Vertex;
+
     dawn::InputState state = AssertWillBeSuccess(device.CreateInputStateBuilder())
-                                 .SetInput(0, 2 * sizeof(float), dawn::InputStepMode::Vertex)
+                                 .SetInput(&input)
                                  .SetAttribute(&attribute1)
                                  .SetAttribute(&attribute2)
                                  .GetResult();
@@ -108,9 +119,7 @@
 // Test that a stride of 0 is valid
 TEST_F(InputStateTest, StrideZero) {
     // Works ok without attributes
-    AssertWillBeSuccess(device.CreateInputStateBuilder())
-        .SetInput(0, 0, dawn::InputStepMode::Vertex)
-        .GetResult();
+    AssertWillBeSuccess(device.CreateInputStateBuilder()).SetInput(&kBaseInput).GetResult();
 
     // Works ok with attributes at a large-ish offset
     dawn::VertexAttributeDescriptor attribute;
@@ -120,7 +129,7 @@
     attribute.format = dawn::VertexFormat::FloatR32;
 
     AssertWillBeSuccess(device.CreateInputStateBuilder())
-        .SetInput(0, 0, dawn::InputStepMode::Vertex)
+        .SetInput(&kBaseInput)
         .SetAttribute(&attribute)
         .GetResult();
 }
@@ -128,28 +137,28 @@
 // Test that we cannot set an already set input
 TEST_F(InputStateTest, AlreadySetInput) {
     // Control case
-    AssertWillBeSuccess(device.CreateInputStateBuilder())
-        .SetInput(0, 0, dawn::InputStepMode::Vertex)
-        .GetResult();
+    AssertWillBeSuccess(device.CreateInputStateBuilder()).SetInput(&kBaseInput).GetResult();
 
     // Oh no, input 0 is set twice
     AssertWillBeError(device.CreateInputStateBuilder())
-        .SetInput(0, 0, dawn::InputStepMode::Vertex)
-        .SetInput(0, 0, dawn::InputStepMode::Vertex)
+        .SetInput(&kBaseInput)
+        .SetInput(&kBaseInput)
         .GetResult();
 }
 
 // Check out of bounds condition on SetInput
 TEST_F(InputStateTest, SetInputOutOfBounds) {
     // Control case, setting last input
-    AssertWillBeSuccess(device.CreateInputStateBuilder())
-        .SetInput(kMaxVertexInputs - 1, 0, dawn::InputStepMode::Vertex)
-        .GetResult();
+    dawn::VertexInputDescriptor input;
+    input.inputSlot = kMaxVertexInputs - 1;
+    input.stride = 0;
+    input.stepMode = dawn::InputStepMode::Vertex;
+
+    AssertWillBeSuccess(device.CreateInputStateBuilder()).SetInput(&input).GetResult();
 
     // Test OOB
-    AssertWillBeError(device.CreateInputStateBuilder())
-        .SetInput(kMaxVertexInputs, 0, dawn::InputStepMode::Vertex)
-        .GetResult();
+    input.inputSlot = kMaxVertexInputs;
+    AssertWillBeError(device.CreateInputStateBuilder()).SetInput(&input).GetResult();
 }
 
 // Test that we cannot set an already set attribute
@@ -162,13 +171,13 @@
     attribute.format = dawn::VertexFormat::FloatR32;
 
     AssertWillBeSuccess(device.CreateInputStateBuilder())
-        .SetInput(0, 0, dawn::InputStepMode::Vertex)
+        .SetInput(&kBaseInput)
         .SetAttribute(&attribute)
         .GetResult();
 
     // Oh no, attribute 0 is set twice
     AssertWillBeError(device.CreateInputStateBuilder())
-        .SetInput(0, 0, dawn::InputStepMode::Vertex)
+        .SetInput(&kBaseInput)
         .SetAttribute(&attribute)
         .SetAttribute(&attribute)
         .GetResult();
@@ -184,14 +193,14 @@
     attribute.format = dawn::VertexFormat::FloatR32;
 
     AssertWillBeSuccess(device.CreateInputStateBuilder())
-        .SetInput(0, 0, dawn::InputStepMode::Vertex)
+        .SetInput(&kBaseInput)
         .SetAttribute(&attribute)
         .GetResult();
 
     // Test OOB
     attribute.shaderLocation = kMaxVertexAttributes;
     AssertWillBeError(device.CreateInputStateBuilder())
-        .SetInput(0, 0, dawn::InputStepMode::Vertex)
+        .SetInput(&kBaseInput)
         .SetAttribute(&attribute)
         .GetResult();
 }
@@ -206,14 +215,14 @@
     attribute.format = dawn::VertexFormat::FloatR32;
 
     AssertWillBeSuccess(device.CreateInputStateBuilder())
-        .SetInput(0, 0, dawn::InputStepMode::Vertex)
+        .SetInput(&kBaseInput)
         .SetAttribute(&attribute)
         .GetResult();
 
     // Attribute 0 uses input 1 which doesn't exist
     attribute.inputSlot = 1;
     AssertWillBeError(device.CreateInputStateBuilder())
-        .SetInput(0, 0, dawn::InputStepMode::Vertex)
+        .SetInput(&kBaseInput)
         .SetAttribute(&attribute)
         .GetResult();
 }
@@ -228,14 +237,14 @@
     attribute.format = dawn::VertexFormat::FloatR32;
 
     AssertWillBeSuccess(device.CreateInputStateBuilder())
-        .SetInput(0, 0, dawn::InputStepMode::Vertex)
+        .SetInput(&kBaseInput)
         .SetAttribute(&attribute)
         .GetResult();
 
     // Could crash if we didn't check for OOB
     attribute.inputSlot = 1000000;
     AssertWillBeError(device.CreateInputStateBuilder())
-        .SetInput(0, 0, dawn::InputStepMode::Vertex)
+        .SetInput(&kBaseInput)
         .SetAttribute(&attribute)
         .GetResult();
 }
diff --git a/src/tests/unittests/validation/VertexBufferValidationTests.cpp b/src/tests/unittests/validation/VertexBufferValidationTests.cpp
index 8b0b053..13038e7 100644
--- a/src/tests/unittests/validation/VertexBufferValidationTests.cpp
+++ b/src/tests/unittests/validation/VertexBufferValidationTests.cpp
@@ -75,11 +75,16 @@
             attribute.offset = 0;
             attribute.format = dawn::VertexFormat::FloatR32G32B32;
 
+            dawn::VertexInputDescriptor input;
+            input.stride = 0;
+            input.stepMode = dawn::InputStepMode::Vertex;
+
             for (unsigned int i = 0; i < numInputs; ++i) {
                 attribute.shaderLocation = i;
                 attribute.inputSlot = i;
+                input.inputSlot = i;
                 builder.SetAttribute(&attribute);
-                builder.SetInput(i, 0, dawn::InputStepMode::Vertex);
+                builder.SetInput(&input);
             }
             return builder.GetResult();
         }