Finish conversion to RenderPipelineDescriptor2

Converts each of the native API backends to use RPD2 natively, started
converting the old format to the new one in the deprecated entry point,
removed all other handling and validation of the old format, and turned
on the deprecation warning.

BUG: dawn:642
Change-Id: I20b671960a83f65ecb4ce6ce1165a563025983cd
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/46726
Reviewed-by: Kai Ninomiya <kainino@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Brandon Jones <bajones@chromium.org>
diff --git a/src/dawn_native/Device.cpp b/src/dawn_native/Device.cpp
index 418865b..9f05587 100644
--- a/src/dawn_native/Device.cpp
+++ b/src/dawn_native/Device.cpp
@@ -532,27 +532,6 @@
     }
 
     ResultOrError<Ref<RenderPipelineBase>> DeviceBase::GetOrCreateRenderPipeline(
-        const RenderPipelineDescriptor* descriptor) {
-        RenderPipelineBase blueprint(this, descriptor);
-
-        const size_t blueprintHash = blueprint.ComputeContentHash();
-        blueprint.SetContentHash(blueprintHash);
-
-        Ref<RenderPipelineBase> result;
-        auto iter = mCaches->renderPipelines.find(&blueprint);
-        if (iter != mCaches->renderPipelines.end()) {
-            result = *iter;
-        } else {
-            DAWN_TRY_ASSIGN(result, CreateRenderPipelineImpl(descriptor));
-            result->SetIsCachedReference();
-            result->SetContentHash(blueprintHash);
-            mCaches->renderPipelines.insert(result.Get());
-        }
-
-        return std::move(result);
-    }
-
-    ResultOrError<Ref<RenderPipelineBase>> DeviceBase::GetOrCreateRenderPipeline(
         const RenderPipelineDescriptor2* descriptor) {
         RenderPipelineBase blueprint(this, descriptor);
 
@@ -564,83 +543,7 @@
         if (iter != mCaches->renderPipelines.end()) {
             result = *iter;
         } else {
-            // Convert descriptor to the older format it before proceeding.
-            // TODO: Convert the rest of the code to operate on the newer format.
-            RenderPipelineDescriptor normalizedDescriptor;
-
-            VertexStateDescriptor vertexState;
-            normalizedDescriptor.vertexState = &vertexState;
-
-            RasterizationStateDescriptor rasterizationState;
-            normalizedDescriptor.rasterizationState = &rasterizationState;
-
-            normalizedDescriptor.label = descriptor->label;
-            normalizedDescriptor.layout = descriptor->layout;
-            normalizedDescriptor.vertexStage.module = descriptor->vertex.module;
-            normalizedDescriptor.vertexStage.entryPoint = descriptor->vertex.entryPoint;
-            normalizedDescriptor.primitiveTopology = descriptor->primitive.topology;
-            normalizedDescriptor.sampleCount = descriptor->multisample.count;
-            normalizedDescriptor.sampleMask = descriptor->multisample.mask;
-            normalizedDescriptor.alphaToCoverageEnabled =
-                descriptor->multisample.alphaToCoverageEnabled;
-
-            vertexState.vertexBufferCount = descriptor->vertex.bufferCount;
-            vertexState.vertexBuffers = descriptor->vertex.buffers;
-            vertexState.indexFormat = descriptor->primitive.stripIndexFormat;
-
-            rasterizationState.frontFace = descriptor->primitive.frontFace;
-            rasterizationState.cullMode = descriptor->primitive.cullMode;
-
-            DepthStencilStateDescriptor depthStencilState;
-            if (descriptor->depthStencil) {
-                const DepthStencilState* depthStencil = descriptor->depthStencil;
-                normalizedDescriptor.depthStencilState = &depthStencilState;
-
-                depthStencilState.format = depthStencil->format;
-                depthStencilState.depthWriteEnabled = depthStencil->depthWriteEnabled;
-                depthStencilState.depthCompare = depthStencil->depthCompare;
-                depthStencilState.stencilFront = depthStencil->stencilFront;
-                depthStencilState.stencilBack = depthStencil->stencilBack;
-                depthStencilState.stencilReadMask = depthStencil->stencilReadMask;
-                depthStencilState.stencilWriteMask = depthStencil->stencilWriteMask;
-                rasterizationState.depthBias = depthStencil->depthBias;
-                rasterizationState.depthBiasSlopeScale = depthStencil->depthBiasSlopeScale;
-                rasterizationState.depthBiasClamp = depthStencil->depthBiasClamp;
-            }
-
-            ProgrammableStageDescriptor fragmentStage;
-            std::vector<ColorStateDescriptor> colorStates;
-            if (descriptor->fragment) {
-                const FragmentState* fragment = descriptor->fragment;
-                normalizedDescriptor.fragmentStage = &fragmentStage;
-
-                fragmentStage.module = fragment->module;
-                fragmentStage.entryPoint = fragment->entryPoint;
-
-                for (uint32_t i = 0; i < fragment->targetCount; ++i) {
-                    const ColorTargetState& target = fragment->targets[i];
-                    ColorStateDescriptor colorState;
-                    colorState.format = target.format;
-                    colorState.writeMask = target.writeMask;
-
-                    if (target.blend) {
-                        const BlendState* blend = target.blend;
-                        colorState.colorBlend.srcFactor = blend->color.srcFactor;
-                        colorState.colorBlend.dstFactor = blend->color.dstFactor;
-                        colorState.colorBlend.operation = blend->color.operation;
-
-                        colorState.alphaBlend.srcFactor = blend->alpha.srcFactor;
-                        colorState.alphaBlend.dstFactor = blend->alpha.dstFactor;
-                        colorState.alphaBlend.operation = blend->alpha.operation;
-                    }
-                    colorStates.push_back(colorState);
-                }
-
-                normalizedDescriptor.colorStateCount = fragment->targetCount;
-                normalizedDescriptor.colorStates = colorStates.data();
-            }
-
-            DAWN_TRY_ASSIGN(result, CreateRenderPipelineImpl(&normalizedDescriptor));
+            DAWN_TRY_ASSIGN(result, CreateRenderPipelineImpl(descriptor));
             result->SetIsCachedReference();
             result->SetContentHash(blueprintHash);
             mCaches->renderPipelines.insert(result.Get());
@@ -870,12 +773,98 @@
         const RenderPipelineDescriptor* descriptor) {
         // TODO: Enable this warning once the tests have been converted to either use the new
         // format or expect the deprecation warning.
-        /*EmitDeprecationWarning(
+        EmitDeprecationWarning(
             "The format of RenderPipelineDescriptor has changed, and will soon require the "
-            "new structure. Please begin using CreateRenderPipeline2() instead.");*/
+            "new structure. Please begin using CreateRenderPipeline2() instead.");
+
+        // Convert descriptor to the new format it before proceeding.
+        RenderPipelineDescriptor2 normalizedDescriptor;
+
+        normalizedDescriptor.label = descriptor->label;
+        normalizedDescriptor.layout = descriptor->layout;
+
+        normalizedDescriptor.vertex.module = descriptor->vertexStage.module;
+        normalizedDescriptor.vertex.entryPoint = descriptor->vertexStage.entryPoint;
+
+        normalizedDescriptor.primitive.topology = descriptor->primitiveTopology;
+
+        normalizedDescriptor.multisample.count = descriptor->sampleCount;
+        normalizedDescriptor.multisample.mask = descriptor->sampleMask;
+        normalizedDescriptor.multisample.alphaToCoverageEnabled =
+            descriptor->alphaToCoverageEnabled;
+
+        if (descriptor->vertexState) {
+            const VertexStateDescriptor* vertexState = descriptor->vertexState;
+            normalizedDescriptor.primitive.stripIndexFormat = vertexState->indexFormat;
+            normalizedDescriptor.vertex.bufferCount = vertexState->vertexBufferCount;
+            normalizedDescriptor.vertex.buffers = vertexState->vertexBuffers;
+        } else {
+            normalizedDescriptor.vertex.bufferCount = 0;
+            normalizedDescriptor.vertex.buffers = nullptr;
+        }
+
+        DepthStencilState depthStencil;
+        if (descriptor->depthStencilState) {
+            const DepthStencilStateDescriptor* depthStencilState = descriptor->depthStencilState;
+            normalizedDescriptor.depthStencil = &depthStencil;
+
+            depthStencil.format = depthStencilState->format;
+            depthStencil.depthWriteEnabled = depthStencilState->depthWriteEnabled;
+            depthStencil.depthCompare = depthStencilState->depthCompare;
+            depthStencil.stencilFront = depthStencilState->stencilFront;
+            depthStencil.stencilBack = depthStencilState->stencilBack;
+            depthStencil.stencilReadMask = depthStencilState->stencilReadMask;
+            depthStencil.stencilWriteMask = depthStencilState->stencilWriteMask;
+        }
+
+        if (descriptor->rasterizationState) {
+            const RasterizationStateDescriptor* rasterizationState = descriptor->rasterizationState;
+            normalizedDescriptor.primitive.frontFace = rasterizationState->frontFace;
+            normalizedDescriptor.primitive.cullMode = rasterizationState->cullMode;
+            depthStencil.depthBias = rasterizationState->depthBias;
+            depthStencil.depthBiasSlopeScale = rasterizationState->depthBiasSlopeScale;
+            depthStencil.depthBiasClamp = rasterizationState->depthBiasClamp;
+        }
+
+        FragmentState fragment;
+        std::vector<ColorTargetState> targets;
+        std::vector<BlendState> blendStates;
+        if (descriptor->fragmentStage) {
+            const ProgrammableStageDescriptor* fragmentStage = descriptor->fragmentStage;
+            normalizedDescriptor.fragment = &fragment;
+
+            fragment.module = fragmentStage->module;
+            fragment.entryPoint = fragmentStage->entryPoint;
+
+            targets.resize(descriptor->colorStateCount);
+            blendStates.resize(descriptor->colorStateCount);
+
+            for (uint32_t i = 0; i < descriptor->colorStateCount; ++i) {
+                const ColorStateDescriptor& colorState = descriptor->colorStates[i];
+                ColorTargetState& target = targets[i];
+                target.format = colorState.format;
+                target.writeMask = colorState.writeMask;
+
+                if (BlendEnabled(&colorState)) {
+                    BlendState* blend = &blendStates[i];
+                    target.blend = blend;
+
+                    blend->color.srcFactor = colorState.colorBlend.srcFactor;
+                    blend->color.dstFactor = colorState.colorBlend.dstFactor;
+                    blend->color.operation = colorState.colorBlend.operation;
+
+                    blend->alpha.srcFactor = colorState.alphaBlend.srcFactor;
+                    blend->alpha.dstFactor = colorState.alphaBlend.dstFactor;
+                    blend->alpha.operation = colorState.alphaBlend.operation;
+                }
+            }
+
+            fragment.targetCount = descriptor->colorStateCount;
+            fragment.targets = targets.data();
+        }
 
         Ref<RenderPipelineBase> result;
-        if (ConsumedError(CreateRenderPipelineInternal(descriptor), &result)) {
+        if (ConsumedError(CreateRenderPipelineInternal(&normalizedDescriptor), &result)) {
             return RenderPipelineBase::MakeError(this);
         }
         return result.Detach();
@@ -1161,30 +1150,6 @@
         }
     }
 
-    ResultOrError<Ref<RenderPipelineBase>> DeviceBase::CreateRenderPipelineInternal(
-        const RenderPipelineDescriptor* descriptor) {
-        DAWN_TRY(ValidateIsAlive());
-
-        if (IsValidationEnabled()) {
-            DAWN_TRY(ValidateRenderPipelineDescriptor(this, descriptor));
-        }
-
-        if (descriptor->layout == nullptr) {
-            RenderPipelineDescriptor descriptorWithDefaultLayout = *descriptor;
-
-            // Ref will keep the pipeline layout alive until the end of the function where
-            // the pipeline will take another reference.
-            Ref<PipelineLayoutBase> layoutRef;
-            DAWN_TRY_ASSIGN(layoutRef,
-                            PipelineLayoutBase::CreateDefault(this, GetStages(descriptor)));
-            descriptorWithDefaultLayout.layout = layoutRef.Get();
-
-            return GetOrCreateRenderPipeline(&descriptorWithDefaultLayout);
-        } else {
-            return GetOrCreateRenderPipeline(descriptor);
-        }
-    }
-
     ResultOrError<Ref<SamplerBase>> DeviceBase::CreateSamplerInternal(
         const SamplerDescriptor* descriptor) {
         const SamplerDescriptor defaultDescriptor = {};
diff --git a/src/dawn_native/Device.h b/src/dawn_native/Device.h
index cf64a38..42c684e 100644
--- a/src/dawn_native/Device.h
+++ b/src/dawn_native/Device.h
@@ -120,8 +120,6 @@
         void UncachePipelineLayout(PipelineLayoutBase* obj);
 
         ResultOrError<Ref<RenderPipelineBase>> GetOrCreateRenderPipeline(
-            const RenderPipelineDescriptor* descriptor);
-        ResultOrError<Ref<RenderPipelineBase>> GetOrCreateRenderPipeline(
             const RenderPipelineDescriptor2* descriptor);
         void UncacheRenderPipeline(RenderPipelineBase* obj);
 
@@ -278,7 +276,7 @@
         virtual ResultOrError<Ref<QuerySetBase>> CreateQuerySetImpl(
             const QuerySetDescriptor* descriptor) = 0;
         virtual ResultOrError<Ref<RenderPipelineBase>> CreateRenderPipelineImpl(
-            const RenderPipelineDescriptor* descriptor) = 0;
+            const RenderPipelineDescriptor2* descriptor) = 0;
         virtual ResultOrError<Ref<SamplerBase>> CreateSamplerImpl(
             const SamplerDescriptor* descriptor) = 0;
         virtual ResultOrError<Ref<ShaderModuleBase>> CreateShaderModuleImpl(
@@ -318,8 +316,6 @@
             const RenderBundleEncoderDescriptor* descriptor);
         ResultOrError<Ref<RenderPipelineBase>> CreateRenderPipelineInternal(
             const RenderPipelineDescriptor2* descriptor);
-        ResultOrError<Ref<RenderPipelineBase>> CreateRenderPipelineInternal(
-            const RenderPipelineDescriptor* descriptor);
         ResultOrError<Ref<SamplerBase>> CreateSamplerInternal(const SamplerDescriptor* descriptor);
         ResultOrError<Ref<ShaderModuleBase>> CreateShaderModuleInternal(
             const ShaderModuleDescriptor* descriptor);
diff --git a/src/dawn_native/RenderPipeline.cpp b/src/dawn_native/RenderPipeline.cpp
index 8dbac0b..15e8e7e 100644
--- a/src/dawn_native/RenderPipeline.cpp
+++ b/src/dawn_native/RenderPipeline.cpp
@@ -270,124 +270,6 @@
             return {};
         }
 
-        // TODO(dawn:642): Validation methods below here are for the deprecated
-        // RenderPipelineDescriptor format and should be removed once it is no longer necessary to
-        // validate that format.
-
-        MaybeError ValidateVertexStateDescriptor(
-            DeviceBase* device,
-            const VertexStateDescriptor* descriptor,
-            wgpu::PrimitiveTopology primitiveTopology,
-            std::bitset<kMaxVertexAttributes>* attributesSetMask) {
-            if (descriptor->nextInChain != nullptr) {
-                return DAWN_VALIDATION_ERROR("nextInChain must be nullptr");
-            }
-            DAWN_TRY(ValidateIndexFormat(descriptor->indexFormat));
-
-            // Pipeline descriptors must have indexFormat != undefined IFF they are using strip
-            // topologies.
-            if (IsStripPrimitiveTopology(primitiveTopology)) {
-                if (descriptor->indexFormat == wgpu::IndexFormat::Undefined) {
-                    return DAWN_VALIDATION_ERROR(
-                        "indexFormat must not be undefined when using strip primitive topologies");
-                }
-            } else if (descriptor->indexFormat != wgpu::IndexFormat::Undefined) {
-                return DAWN_VALIDATION_ERROR(
-                    "indexFormat must be undefined when using non-strip primitive topologies");
-            }
-
-            if (descriptor->vertexBufferCount > kMaxVertexBuffers) {
-                return DAWN_VALIDATION_ERROR("Vertex buffer count exceeds maximum");
-            }
-
-            uint32_t totalAttributesNum = 0;
-            for (uint32_t i = 0; i < descriptor->vertexBufferCount; ++i) {
-                DAWN_TRY(ValidateVertexBufferLayout(device, &descriptor->vertexBuffers[i],
-                                                    attributesSetMask));
-                totalAttributesNum += descriptor->vertexBuffers[i].attributeCount;
-            }
-
-            // Every vertex attribute has a member called shaderLocation, and there are some
-            // requirements for shaderLocation: 1) >=0, 2) values are different across different
-            // attributes, 3) can't exceed kMaxVertexAttributes. So it can ensure that total
-            // attribute number never exceed kMaxVertexAttributes.
-            ASSERT(totalAttributesNum <= kMaxVertexAttributes);
-
-            return {};
-        }
-
-        MaybeError ValidateRasterizationStateDescriptor(
-            const RasterizationStateDescriptor* descriptor) {
-            if (descriptor->nextInChain != nullptr) {
-                return DAWN_VALIDATION_ERROR("nextInChain must be nullptr");
-            }
-
-            DAWN_TRY(ValidateFrontFace(descriptor->frontFace));
-            DAWN_TRY(ValidateCullMode(descriptor->cullMode));
-
-            if (std::isnan(descriptor->depthBiasSlopeScale) ||
-                std::isnan(descriptor->depthBiasClamp)) {
-                return DAWN_VALIDATION_ERROR("Depth bias parameters must not be NaN.");
-            }
-
-            return {};
-        }
-
-        MaybeError ValidateColorStateDescriptor(const DeviceBase* device,
-                                                const ColorStateDescriptor& descriptor,
-                                                bool fragmentWritten,
-                                                wgpu::TextureComponentType fragmentOutputBaseType) {
-            if (descriptor.nextInChain != nullptr) {
-                return DAWN_VALIDATION_ERROR("nextInChain must be nullptr");
-            }
-            DAWN_TRY(ValidateBlendOperation(descriptor.alphaBlend.operation));
-            DAWN_TRY(ValidateBlendFactor(descriptor.alphaBlend.srcFactor));
-            DAWN_TRY(ValidateBlendFactor(descriptor.alphaBlend.dstFactor));
-            DAWN_TRY(ValidateBlendOperation(descriptor.colorBlend.operation));
-            DAWN_TRY(ValidateBlendFactor(descriptor.colorBlend.srcFactor));
-            DAWN_TRY(ValidateBlendFactor(descriptor.colorBlend.dstFactor));
-            DAWN_TRY(ValidateColorWriteMask(descriptor.writeMask));
-
-            const Format* format;
-            DAWN_TRY_ASSIGN(format, device->GetInternalFormat(descriptor.format));
-            if (!format->IsColor() || !format->isRenderable) {
-                return DAWN_VALIDATION_ERROR("Color format must be color renderable");
-            }
-            if (fragmentWritten &&
-                fragmentOutputBaseType != format->GetAspectInfo(Aspect::Color).baseType) {
-                return DAWN_VALIDATION_ERROR(
-                    "Color format must match the fragment stage output type");
-            }
-
-            return {};
-        }
-
-        MaybeError ValidateDepthStencilStateDescriptor(
-            const DeviceBase* device,
-            const DepthStencilStateDescriptor* descriptor) {
-            if (descriptor->nextInChain != nullptr) {
-                return DAWN_VALIDATION_ERROR("nextInChain must be nullptr");
-            }
-            DAWN_TRY(ValidateCompareFunction(descriptor->depthCompare));
-            DAWN_TRY(ValidateCompareFunction(descriptor->stencilFront.compare));
-            DAWN_TRY(ValidateStencilOperation(descriptor->stencilFront.failOp));
-            DAWN_TRY(ValidateStencilOperation(descriptor->stencilFront.depthFailOp));
-            DAWN_TRY(ValidateStencilOperation(descriptor->stencilFront.passOp));
-            DAWN_TRY(ValidateCompareFunction(descriptor->stencilBack.compare));
-            DAWN_TRY(ValidateStencilOperation(descriptor->stencilBack.failOp));
-            DAWN_TRY(ValidateStencilOperation(descriptor->stencilBack.depthFailOp));
-            DAWN_TRY(ValidateStencilOperation(descriptor->stencilBack.passOp));
-
-            const Format* format;
-            DAWN_TRY_ASSIGN(format, device->GetInternalFormat(descriptor->format));
-            if (!format->HasDepthOrStencil() || !format->isRenderable) {
-                return DAWN_VALIDATION_ERROR(
-                    "Depth stencil format must be depth-stencil renderable");
-            }
-
-            return {};
-        }
-
     }  // anonymous namespace
 
     // Helper functions
@@ -408,82 +290,6 @@
     }
 
     MaybeError ValidateRenderPipelineDescriptor(DeviceBase* device,
-                                                const RenderPipelineDescriptor* descriptor) {
-        if (descriptor->nextInChain != nullptr) {
-            return DAWN_VALIDATION_ERROR("nextInChain must be nullptr");
-        }
-
-        if (descriptor->layout != nullptr) {
-            DAWN_TRY(device->ValidateObject(descriptor->layout));
-        }
-
-        // TODO(crbug.com/dawn/136): Support vertex-only pipelines.
-        if (descriptor->fragmentStage == nullptr) {
-            return DAWN_VALIDATION_ERROR("Null fragment stage is not supported (yet)");
-        }
-
-        DAWN_TRY(ValidatePrimitiveTopology(descriptor->primitiveTopology));
-
-        std::bitset<kMaxVertexAttributes> attributesSetMask;
-        if (descriptor->vertexState) {
-            DAWN_TRY(ValidateVertexStateDescriptor(device,
-                descriptor->vertexState, descriptor->primitiveTopology, &attributesSetMask));
-        }
-
-        DAWN_TRY(ValidateProgrammableStage(device, descriptor->vertexStage.module,
-                                           descriptor->vertexStage.entryPoint, descriptor->layout,
-                                           SingleShaderStage::Vertex));
-        DAWN_TRY(ValidateProgrammableStage(device, descriptor->fragmentStage->module,
-                                           descriptor->fragmentStage->entryPoint,
-                                           descriptor->layout, SingleShaderStage::Fragment));
-
-        if (descriptor->rasterizationState) {
-            DAWN_TRY(ValidateRasterizationStateDescriptor(descriptor->rasterizationState));
-        }
-
-        const EntryPointMetadata& vertexMetadata =
-            descriptor->vertexStage.module->GetEntryPoint(descriptor->vertexStage.entryPoint);
-        if (!IsSubset(vertexMetadata.usedVertexAttributes, attributesSetMask)) {
-            return DAWN_VALIDATION_ERROR(
-                "Pipeline vertex stage uses vertex buffers not in the vertex state");
-        }
-
-        if (!IsValidSampleCount(descriptor->sampleCount)) {
-            return DAWN_VALIDATION_ERROR("Sample count is not supported");
-        }
-
-        if (descriptor->colorStateCount > kMaxColorAttachments) {
-            return DAWN_VALIDATION_ERROR("Color States number exceeds maximum");
-        }
-
-        if (descriptor->colorStateCount == 0 && !descriptor->depthStencilState) {
-            return DAWN_VALIDATION_ERROR(
-                "Should have at least one colorState or a depthStencilState");
-        }
-
-        ASSERT(descriptor->fragmentStage != nullptr);
-        const EntryPointMetadata& fragmentMetadata =
-            descriptor->fragmentStage->module->GetEntryPoint(descriptor->fragmentStage->entryPoint);
-        for (ColorAttachmentIndex i(uint8_t(0));
-             i < ColorAttachmentIndex(static_cast<uint8_t>(descriptor->colorStateCount)); ++i) {
-            DAWN_TRY(ValidateColorStateDescriptor(
-                device, descriptor->colorStates[static_cast<uint8_t>(i)],
-                fragmentMetadata.fragmentOutputsWritten[i],
-                fragmentMetadata.fragmentOutputFormatBaseTypes[i]));
-        }
-
-        if (descriptor->depthStencilState) {
-            DAWN_TRY(ValidateDepthStencilStateDescriptor(device, descriptor->depthStencilState));
-        }
-
-        if (descriptor->alphaToCoverageEnabled && descriptor->sampleCount <= 1) {
-            return DAWN_VALIDATION_ERROR("Enabling alphaToCoverage requires sampleCount > 1");
-        }
-
-        return {};
-    }
-
-    MaybeError ValidateRenderPipelineDescriptor(DeviceBase* device,
                                                 const RenderPipelineDescriptor2* descriptor) {
         if (descriptor->nextInChain != nullptr) {
             return DAWN_VALIDATION_ERROR("nextInChain must be nullptr");
@@ -518,17 +324,6 @@
         return {};
     }
 
-    std::vector<StageAndDescriptor> GetStages(const RenderPipelineDescriptor* descriptor) {
-        std::vector<StageAndDescriptor> stages;
-        stages.push_back({SingleShaderStage::Vertex, descriptor->vertexStage.module,
-                          descriptor->vertexStage.entryPoint});
-        if (descriptor->fragmentStage != nullptr) {
-            stages.push_back({SingleShaderStage::Fragment, descriptor->fragmentStage->module,
-                              descriptor->fragmentStage->entryPoint});
-        }
-        return stages;
-    }
-
     std::vector<StageAndDescriptor> GetStages(const RenderPipelineDescriptor2* descriptor) {
         std::vector<StageAndDescriptor> stages;
         stages.push_back(
@@ -563,118 +358,6 @@
     // RenderPipelineBase
 
     RenderPipelineBase::RenderPipelineBase(DeviceBase* device,
-                                           const RenderPipelineDescriptor* descriptor)
-        : PipelineBase(device,
-                       descriptor->layout,
-                       {{SingleShaderStage::Vertex, descriptor->vertexStage.module,
-                         descriptor->vertexStage.entryPoint},
-                        {SingleShaderStage::Fragment, descriptor->fragmentStage->module,
-                         descriptor->fragmentStage->entryPoint}}),
-          mAttachmentState(device->GetOrCreateAttachmentState(descriptor)) {
-        mPrimitive.topology = descriptor->primitiveTopology;
-
-        mMultisample.count = descriptor->sampleCount;
-        mMultisample.mask = descriptor->sampleMask;
-        mMultisample.alphaToCoverageEnabled = descriptor->alphaToCoverageEnabled;
-
-        if (descriptor->vertexState != nullptr) {
-            const VertexStateDescriptor& vertexState = *descriptor->vertexState;
-            mVertexBufferCount = vertexState.vertexBufferCount;
-            mPrimitive.stripIndexFormat = vertexState.indexFormat;
-
-            for (uint8_t slot = 0; slot < mVertexBufferCount; ++slot) {
-                if (vertexState.vertexBuffers[slot].attributeCount == 0) {
-                    continue;
-                }
-
-                VertexBufferSlot typedSlot(slot);
-
-                mVertexBufferSlotsUsed.set(typedSlot);
-                mVertexBufferInfos[typedSlot].arrayStride =
-                    vertexState.vertexBuffers[slot].arrayStride;
-                mVertexBufferInfos[typedSlot].stepMode = vertexState.vertexBuffers[slot].stepMode;
-
-                for (uint32_t i = 0; i < vertexState.vertexBuffers[slot].attributeCount; ++i) {
-                    VertexAttributeLocation location = VertexAttributeLocation(static_cast<uint8_t>(
-                        vertexState.vertexBuffers[slot].attributes[i].shaderLocation));
-                    mAttributeLocationsUsed.set(location);
-                    mAttributeInfos[location].shaderLocation = location;
-                    mAttributeInfos[location].vertexBufferSlot = typedSlot;
-                    mAttributeInfos[location].offset =
-                        vertexState.vertexBuffers[slot].attributes[i].offset;
-
-                    mAttributeInfos[location].format = dawn::NormalizeVertexFormat(
-                        vertexState.vertexBuffers[slot].attributes[i].format);
-                }
-            }
-        } else {
-            mVertexBufferCount = 0;
-            mPrimitive.stripIndexFormat = wgpu::IndexFormat::Undefined;
-        }
-
-        if (mAttachmentState->HasDepthStencilAttachment()) {
-            const DepthStencilStateDescriptor& depthStencil = *descriptor->depthStencilState;
-            mDepthStencil.format = depthStencil.format;
-            mDepthStencil.depthWriteEnabled = depthStencil.depthWriteEnabled;
-            mDepthStencil.depthCompare = depthStencil.depthCompare;
-            mDepthStencil.stencilBack = depthStencil.stencilBack;
-            mDepthStencil.stencilFront = depthStencil.stencilFront;
-            mDepthStencil.stencilReadMask = depthStencil.stencilReadMask;
-            mDepthStencil.stencilWriteMask = depthStencil.stencilWriteMask;
-        } else {
-            // These default values below are useful for backends to fill information.
-            // The values indicate that depth and stencil test are disabled when backends
-            // set their own depth stencil states/descriptors according to the values in
-            // mDepthStencil.
-            mDepthStencil.format = wgpu::TextureFormat::Undefined;
-            mDepthStencil.depthWriteEnabled = false;
-            mDepthStencil.depthCompare = wgpu::CompareFunction::Always;
-            mDepthStencil.stencilBack.compare = wgpu::CompareFunction::Always;
-            mDepthStencil.stencilBack.failOp = wgpu::StencilOperation::Keep;
-            mDepthStencil.stencilBack.depthFailOp = wgpu::StencilOperation::Keep;
-            mDepthStencil.stencilBack.passOp = wgpu::StencilOperation::Keep;
-            mDepthStencil.stencilFront.compare = wgpu::CompareFunction::Always;
-            mDepthStencil.stencilFront.failOp = wgpu::StencilOperation::Keep;
-            mDepthStencil.stencilFront.depthFailOp = wgpu::StencilOperation::Keep;
-            mDepthStencil.stencilFront.passOp = wgpu::StencilOperation::Keep;
-            mDepthStencil.stencilReadMask = 0xff;
-            mDepthStencil.stencilWriteMask = 0xff;
-        }
-
-        if (descriptor->rasterizationState != nullptr) {
-            mPrimitive.frontFace = descriptor->rasterizationState->frontFace;
-            mPrimitive.cullMode = descriptor->rasterizationState->cullMode;
-            mDepthStencil.depthBias = descriptor->rasterizationState->depthBias;
-            mDepthStencil.depthBiasSlopeScale = descriptor->rasterizationState->depthBiasSlopeScale;
-            mDepthStencil.depthBiasClamp = descriptor->rasterizationState->depthBiasClamp;
-        } else {
-            mPrimitive.frontFace = wgpu::FrontFace::CCW;
-            mPrimitive.cullMode = wgpu::CullMode::None;
-            mDepthStencil.depthBias = 0;
-            mDepthStencil.depthBiasSlopeScale = 0.0f;
-            mDepthStencil.depthBiasClamp = 0.0f;
-        }
-
-        for (ColorAttachmentIndex i : IterateBitSet(mAttachmentState->GetColorAttachmentsMask())) {
-            const ColorStateDescriptor* colorState =
-                &descriptor->colorStates[static_cast<uint8_t>(i)];
-            mTargets[i].format = colorState->format;
-            mTargets[i].writeMask = colorState->writeMask;
-
-            if (BlendEnabled(colorState)) {
-                mTargetBlend[i].color = colorState->colorBlend;
-                mTargetBlend[i].alpha = colorState->alphaBlend;
-                mTargets[i].blend = &mTargetBlend[i];
-            } else {
-                mTargets[i].blend = nullptr;
-            }
-        }
-
-        // TODO(cwallez@chromium.org): Check against the shader module that the correct color
-        // attachment are set?
-    }
-
-    RenderPipelineBase::RenderPipelineBase(DeviceBase* device,
                                            const RenderPipelineDescriptor2* descriptor)
         : PipelineBase(device,
                        descriptor->layout,
diff --git a/src/dawn_native/RenderPipeline.h b/src/dawn_native/RenderPipeline.h
index eb1820e..0ee90b5 100644
--- a/src/dawn_native/RenderPipeline.h
+++ b/src/dawn_native/RenderPipeline.h
@@ -30,11 +30,8 @@
     class DeviceBase;
 
     MaybeError ValidateRenderPipelineDescriptor(DeviceBase* device,
-                                                const RenderPipelineDescriptor* descriptor);
-    MaybeError ValidateRenderPipelineDescriptor(DeviceBase* device,
                                                 const RenderPipelineDescriptor2* descriptor);
 
-    std::vector<StageAndDescriptor> GetStages(const RenderPipelineDescriptor* descriptor);
     std::vector<StageAndDescriptor> GetStages(const RenderPipelineDescriptor2* descriptor);
 
     size_t IndexFormatSize(wgpu::IndexFormat format);
@@ -43,6 +40,8 @@
 
     bool StencilTestEnabled(const DepthStencilState* mDepthStencil);
 
+    bool BlendEnabled(const ColorStateDescriptor* mColorState);
+
     struct VertexAttributeInfo {
         wgpu::VertexFormat format;
         uint64_t offset;
@@ -57,7 +56,6 @@
 
     class RenderPipelineBase : public PipelineBase {
       public:
-        RenderPipelineBase(DeviceBase* device, const RenderPipelineDescriptor* descriptor);
         RenderPipelineBase(DeviceBase* device, const RenderPipelineDescriptor2* descriptor);
         ~RenderPipelineBase() override;
 
diff --git a/src/dawn_native/ShaderModule.cpp b/src/dawn_native/ShaderModule.cpp
index 0cca505..de290db 100644
--- a/src/dawn_native/ShaderModule.cpp
+++ b/src/dawn_native/ShaderModule.cpp
@@ -1145,14 +1145,14 @@
     }
 
     std::unique_ptr<tint::transform::VertexPulling> MakeVertexPullingTransform(
-        const VertexStateDescriptor& vertexState,
+        const VertexState& vertexState,
         const std::string& entryPoint,
         BindGroupIndex pullingBufferBindingSet) {
         tint::transform::VertexPulling::Config cfg;
         cfg.entry_point_name = entryPoint;
         cfg.pulling_group = static_cast<uint32_t>(pullingBufferBindingSet);
-        for (uint32_t i = 0; i < vertexState.vertexBufferCount; ++i) {
-            const auto& vertexBuffer = vertexState.vertexBuffers[i];
+        for (uint32_t i = 0; i < vertexState.bufferCount; ++i) {
+            const auto& vertexBuffer = vertexState.buffers[i];
             tint::transform::VertexBufferLayoutDescriptor layout;
             layout.array_stride = vertexBuffer.arrayStride;
             layout.step_mode = ToTintInputStepMode(vertexBuffer.stepMode);
@@ -1267,7 +1267,7 @@
 
     ResultOrError<std::vector<uint32_t>> ShaderModuleBase::GeneratePullingSpirv(
         const std::vector<uint32_t>& spirv,
-        const VertexStateDescriptor& vertexState,
+        const VertexState& vertexState,
         const std::string& entryPoint,
         BindGroupIndex pullingBufferBindingSet) const {
         tint::Program program;
@@ -1278,7 +1278,7 @@
 
     ResultOrError<std::vector<uint32_t>> ShaderModuleBase::GeneratePullingSpirv(
         const tint::Program* programIn,
-        const VertexStateDescriptor& vertexState,
+        const VertexState& vertexState,
         const std::string& entryPoint,
         BindGroupIndex pullingBufferBindingSet) const {
         std::ostringstream errorStream;
diff --git a/src/dawn_native/ShaderModule.h b/src/dawn_native/ShaderModule.h
index 3d500a5..2f00962 100644
--- a/src/dawn_native/ShaderModule.h
+++ b/src/dawn_native/ShaderModule.h
@@ -77,7 +77,7 @@
                                                const tint::Program* program);
 
     std::unique_ptr<tint::transform::VertexPulling> MakeVertexPullingTransform(
-        const VertexStateDescriptor& vertexState,
+        const VertexState& vertexState,
         const std::string& entryPoint,
         BindGroupIndex pullingBufferBindingSet);
 
@@ -145,13 +145,13 @@
 
         ResultOrError<std::vector<uint32_t>> GeneratePullingSpirv(
             const std::vector<uint32_t>& spirv,
-            const VertexStateDescriptor& vertexState,
+            const VertexState& vertexState,
             const std::string& entryPoint,
             BindGroupIndex pullingBufferBindingSet) const;
 
         ResultOrError<std::vector<uint32_t>> GeneratePullingSpirv(
             const tint::Program* program,
-            const VertexStateDescriptor& vertexState,
+            const VertexState& vertexState,
             const std::string& entryPoint,
             BindGroupIndex pullingBufferBindingSet) const;
 
diff --git a/src/dawn_native/d3d12/DeviceD3D12.cpp b/src/dawn_native/d3d12/DeviceD3D12.cpp
index e03c034..2c09181 100644
--- a/src/dawn_native/d3d12/DeviceD3D12.cpp
+++ b/src/dawn_native/d3d12/DeviceD3D12.cpp
@@ -326,7 +326,7 @@
         return QuerySet::Create(this, descriptor);
     }
     ResultOrError<Ref<RenderPipelineBase>> Device::CreateRenderPipelineImpl(
-        const RenderPipelineDescriptor* descriptor) {
+        const RenderPipelineDescriptor2* descriptor) {
         return RenderPipeline::Create(this, descriptor);
     }
     ResultOrError<Ref<SamplerBase>> Device::CreateSamplerImpl(const SamplerDescriptor* descriptor) {
diff --git a/src/dawn_native/d3d12/DeviceD3D12.h b/src/dawn_native/d3d12/DeviceD3D12.h
index 3867e41..177c943 100644
--- a/src/dawn_native/d3d12/DeviceD3D12.h
+++ b/src/dawn_native/d3d12/DeviceD3D12.h
@@ -154,7 +154,7 @@
         ResultOrError<Ref<QuerySetBase>> CreateQuerySetImpl(
             const QuerySetDescriptor* descriptor) override;
         ResultOrError<Ref<RenderPipelineBase>> CreateRenderPipelineImpl(
-            const RenderPipelineDescriptor* descriptor) override;
+            const RenderPipelineDescriptor2* descriptor) override;
         ResultOrError<Ref<SamplerBase>> CreateSamplerImpl(
             const SamplerDescriptor* descriptor) override;
         ResultOrError<Ref<ShaderModuleBase>> CreateShaderModuleImpl(
diff --git a/src/dawn_native/d3d12/RenderPipelineD3D12.cpp b/src/dawn_native/d3d12/RenderPipelineD3D12.cpp
index 713d2c1..3aea032 100644
--- a/src/dawn_native/d3d12/RenderPipelineD3D12.cpp
+++ b/src/dawn_native/d3d12/RenderPipelineD3D12.cpp
@@ -297,13 +297,13 @@
 
     ResultOrError<Ref<RenderPipeline>> RenderPipeline::Create(
         Device* device,
-        const RenderPipelineDescriptor* descriptor) {
+        const RenderPipelineDescriptor2* descriptor) {
         Ref<RenderPipeline> pipeline = AcquireRef(new RenderPipeline(device, descriptor));
         DAWN_TRY(pipeline->Initialize(descriptor));
         return pipeline;
     }
 
-    MaybeError RenderPipeline::Initialize(const RenderPipelineDescriptor* descriptor) {
+    MaybeError RenderPipeline::Initialize(const RenderPipelineDescriptor2* descriptor) {
         Device* device = ToBackend(GetDevice());
         uint32_t compileFlags = 0;
 #if defined(_DEBUG)
@@ -316,12 +316,12 @@
         D3D12_GRAPHICS_PIPELINE_STATE_DESC descriptorD3D12 = {};
 
         PerStage<const char*> entryPoints;
-        entryPoints[SingleShaderStage::Vertex] = descriptor->vertexStage.entryPoint;
-        entryPoints[SingleShaderStage::Fragment] = descriptor->fragmentStage->entryPoint;
+        entryPoints[SingleShaderStage::Vertex] = descriptor->vertex.entryPoint;
+        entryPoints[SingleShaderStage::Fragment] = descriptor->fragment->entryPoint;
 
         PerStage<ShaderModule*> modules;
-        modules[SingleShaderStage::Vertex] = ToBackend(descriptor->vertexStage.module);
-        modules[SingleShaderStage::Fragment] = ToBackend(descriptor->fragmentStage->module);
+        modules[SingleShaderStage::Vertex] = ToBackend(descriptor->vertex.module);
+        modules[SingleShaderStage::Fragment] = ToBackend(descriptor->fragment->module);
 
         PerStage<D3D12_SHADER_BYTECODE*> shaders;
         shaders[SingleShaderStage::Vertex] = &descriptorD3D12.VS;
@@ -377,7 +377,7 @@
         }
         descriptorD3D12.NumRenderTargets = static_cast<uint32_t>(GetColorAttachmentsMask().count());
 
-        descriptorD3D12.BlendState.AlphaToCoverageEnable = descriptor->alphaToCoverageEnabled;
+        descriptorD3D12.BlendState.AlphaToCoverageEnable = IsAlphaToCoverageEnabled();
         descriptorD3D12.BlendState.IndependentBlendEnable = TRUE;
 
         descriptorD3D12.DepthStencilState = ComputeDepthStencilDesc(GetDepthStencilState());
diff --git a/src/dawn_native/d3d12/RenderPipelineD3D12.h b/src/dawn_native/d3d12/RenderPipelineD3D12.h
index c99d0a1..bb82b8d 100644
--- a/src/dawn_native/d3d12/RenderPipelineD3D12.h
+++ b/src/dawn_native/d3d12/RenderPipelineD3D12.h
@@ -28,7 +28,7 @@
       public:
         static ResultOrError<Ref<RenderPipeline>> Create(
             Device* device,
-            const RenderPipelineDescriptor* descriptor);
+            const RenderPipelineDescriptor2* descriptor);
         RenderPipeline() = delete;
 
         D3D12_PRIMITIVE_TOPOLOGY GetD3D12PrimitiveTopology() const;
@@ -39,7 +39,7 @@
       private:
         ~RenderPipeline() override;
         using RenderPipelineBase::RenderPipelineBase;
-        MaybeError Initialize(const RenderPipelineDescriptor* descriptor);
+        MaybeError Initialize(const RenderPipelineDescriptor2* descriptor);
         D3D12_INPUT_LAYOUT_DESC ComputeInputLayout(
             std::array<D3D12_INPUT_ELEMENT_DESC, kMaxVertexAttributes>* inputElementDescriptors);
 
diff --git a/src/dawn_native/metal/DeviceMTL.h b/src/dawn_native/metal/DeviceMTL.h
index 90ef4fd..ae97727 100644
--- a/src/dawn_native/metal/DeviceMTL.h
+++ b/src/dawn_native/metal/DeviceMTL.h
@@ -91,7 +91,7 @@
         ResultOrError<Ref<QuerySetBase>> CreateQuerySetImpl(
             const QuerySetDescriptor* descriptor) override;
         ResultOrError<Ref<RenderPipelineBase>> CreateRenderPipelineImpl(
-            const RenderPipelineDescriptor* descriptor) override;
+            const RenderPipelineDescriptor2* descriptor) override;
         ResultOrError<Ref<SamplerBase>> CreateSamplerImpl(
             const SamplerDescriptor* descriptor) override;
         ResultOrError<Ref<ShaderModuleBase>> CreateShaderModuleImpl(
diff --git a/src/dawn_native/metal/DeviceMTL.mm b/src/dawn_native/metal/DeviceMTL.mm
index 85fb511..34c39d2 100644
--- a/src/dawn_native/metal/DeviceMTL.mm
+++ b/src/dawn_native/metal/DeviceMTL.mm
@@ -146,7 +146,7 @@
         return QuerySet::Create(this, descriptor);
     }
     ResultOrError<Ref<RenderPipelineBase>> Device::CreateRenderPipelineImpl(
-        const RenderPipelineDescriptor* descriptor) {
+        const RenderPipelineDescriptor2* descriptor) {
         return RenderPipeline::Create(this, descriptor);
     }
     ResultOrError<Ref<SamplerBase>> Device::CreateSamplerImpl(const SamplerDescriptor* descriptor) {
diff --git a/src/dawn_native/metal/RenderPipelineMTL.h b/src/dawn_native/metal/RenderPipelineMTL.h
index 43eebec..19ea284 100644
--- a/src/dawn_native/metal/RenderPipelineMTL.h
+++ b/src/dawn_native/metal/RenderPipelineMTL.h
@@ -29,7 +29,7 @@
       public:
         static ResultOrError<Ref<RenderPipeline>> Create(
             Device* device,
-            const RenderPipelineDescriptor* descriptor);
+            const RenderPipelineDescriptor2* descriptor);
 
         MTLPrimitiveType GetMTLPrimitiveTopology() const;
         MTLWinding GetMTLFrontFace() const;
@@ -47,7 +47,7 @@
 
       private:
         using RenderPipelineBase::RenderPipelineBase;
-        MaybeError Initialize(const RenderPipelineDescriptor* descriptor);
+        MaybeError Initialize(const RenderPipelineDescriptor2* descriptor);
 
         MTLVertexDescriptor* MakeVertexDesc();
 
diff --git a/src/dawn_native/metal/RenderPipelineMTL.mm b/src/dawn_native/metal/RenderPipelineMTL.mm
index 27f7f3e..8da8618 100644
--- a/src/dawn_native/metal/RenderPipelineMTL.mm
+++ b/src/dawn_native/metal/RenderPipelineMTL.mm
@@ -312,13 +312,13 @@
     // static
     ResultOrError<Ref<RenderPipeline>> RenderPipeline::Create(
         Device* device,
-        const RenderPipelineDescriptor* descriptor) {
+        const RenderPipelineDescriptor2* descriptor) {
         Ref<RenderPipeline> pipeline = AcquireRef(new RenderPipeline(device, descriptor));
         DAWN_TRY(pipeline->Initialize(descriptor));
         return pipeline;
     }
 
-    MaybeError RenderPipeline::Initialize(const RenderPipelineDescriptor* descriptor) {
+    MaybeError RenderPipeline::Initialize(const RenderPipelineDescriptor2* descriptor) {
         mMtlPrimitiveTopology = MTLPrimitiveTopology(GetPrimitiveTopology());
         mMtlFrontFace = MTLFrontFace(GetFrontFace());
         mMtlCullMode = ToMTLCullMode(GetCullMode());
@@ -338,12 +338,12 @@
         }
         descriptorMTL.vertexDescriptor = vertexDesc.Get();
 
-        ShaderModule* vertexModule = ToBackend(descriptor->vertexStage.module);
-        const char* vertexEntryPoint = descriptor->vertexStage.entryPoint;
+        ShaderModule* vertexModule = ToBackend(descriptor->vertex.module);
+        const char* vertexEntryPoint = descriptor->vertex.entryPoint;
         ShaderModule::MetalFunctionData vertexData;
 
-        const VertexStateDescriptor* vertexStatePtr = descriptor->vertexState;
-        VertexStateDescriptor vertexState;
+        const VertexState* vertexStatePtr = &descriptor->vertex;
+        VertexState vertexState;
         if (vertexStatePtr == nullptr) {
             vertexState = {};
             vertexStatePtr = &vertexState;
@@ -358,12 +358,12 @@
             mStagesRequiringStorageBufferLength |= wgpu::ShaderStage::Vertex;
         }
 
-        ShaderModule* fragmentModule = ToBackend(descriptor->fragmentStage->module);
-        const char* fragmentEntryPoint = descriptor->fragmentStage->entryPoint;
+        ShaderModule* fragmentModule = ToBackend(descriptor->fragment->module);
+        const char* fragmentEntryPoint = descriptor->fragment->entryPoint;
         ShaderModule::MetalFunctionData fragmentData;
         DAWN_TRY(fragmentModule->CreateFunction(fragmentEntryPoint, SingleShaderStage::Fragment,
                                                 ToBackend(GetLayout()), &fragmentData,
-                                                descriptor->sampleMask));
+                                                GetSampleMask()));
 
         descriptorMTL.fragmentFunction = fragmentData.function.Get();
         if (fragmentData.needsStorageBufferLength) {
@@ -395,7 +395,7 @@
 
         descriptorMTL.inputPrimitiveTopology = MTLInputPrimitiveTopology(GetPrimitiveTopology());
         descriptorMTL.sampleCount = GetSampleCount();
-        descriptorMTL.alphaToCoverageEnabled = descriptor->alphaToCoverageEnabled;
+        descriptorMTL.alphaToCoverageEnabled = IsAlphaToCoverageEnabled();
 
         {
             NSError* error = nullptr;
diff --git a/src/dawn_native/metal/ShaderModuleMTL.h b/src/dawn_native/metal/ShaderModuleMTL.h
index e8bd1a9..2cfdf49 100644
--- a/src/dawn_native/metal/ShaderModuleMTL.h
+++ b/src/dawn_native/metal/ShaderModuleMTL.h
@@ -48,7 +48,7 @@
                                   MetalFunctionData* out,
                                   uint32_t sampleMask = 0xFFFFFFFF,
                                   const RenderPipeline* renderPipeline = nullptr,
-                                  const VertexStateDescriptor* vertexState = nullptr);
+                                  const VertexState* vertexState = nullptr);
 
       private:
         ResultOrError<std::string> TranslateToMSLWithTint(const char* entryPointName,
@@ -56,7 +56,7 @@
                                                           const PipelineLayout* layout,
                                                           uint32_t sampleMask,
                                                           const RenderPipeline* renderPipeline,
-                                                          const VertexStateDescriptor* vertexState,
+                                                          const VertexState* vertexState,
                                                           std::string* remappedEntryPointName,
                                                           bool* needsStorageBufferLength);
         ResultOrError<std::string> TranslateToMSLWithSPIRVCross(
@@ -65,7 +65,7 @@
             const PipelineLayout* layout,
             uint32_t sampleMask,
             const RenderPipeline* renderPipeline,
-            const VertexStateDescriptor* vertexState,
+            const VertexState* vertexState,
             std::string* remappedEntryPointName,
             bool* needsStorageBufferLength);
 
diff --git a/src/dawn_native/metal/ShaderModuleMTL.mm b/src/dawn_native/metal/ShaderModuleMTL.mm
index c65e0e8..d302ce7 100644
--- a/src/dawn_native/metal/ShaderModuleMTL.mm
+++ b/src/dawn_native/metal/ShaderModuleMTL.mm
@@ -58,7 +58,7 @@
         // TODO(crbug.com/tint/387): AND in a fixed sample mask in the shader.
         uint32_t sampleMask,
         const RenderPipeline* renderPipeline,
-        const VertexStateDescriptor* vertexState,
+        const VertexState* vertexState,
         std::string* remappedEntryPointName,
         bool* needsStorageBufferLength) {
         // TODO(crbug.com/tint/256): Set this accordingly if arrayLength(..) is used.
@@ -122,7 +122,7 @@
         const PipelineLayout* layout,
         uint32_t sampleMask,
         const RenderPipeline* renderPipeline,
-        const VertexStateDescriptor* vertexState,
+        const VertexState* vertexState,
         std::string* remappedEntryPointName,
         bool* needsStorageBufferLength) {
         const std::vector<uint32_t>* spirv = &GetSpirv();
@@ -232,7 +232,7 @@
                                             ShaderModule::MetalFunctionData* out,
                                             uint32_t sampleMask,
                                             const RenderPipeline* renderPipeline,
-                                            const VertexStateDescriptor* vertexState) {
+                                            const VertexState* vertexState) {
         ASSERT(!IsError());
         ASSERT(out);
 
diff --git a/src/dawn_native/null/DeviceNull.cpp b/src/dawn_native/null/DeviceNull.cpp
index a6ee029..13d6818 100644
--- a/src/dawn_native/null/DeviceNull.cpp
+++ b/src/dawn_native/null/DeviceNull.cpp
@@ -122,7 +122,7 @@
         return AcquireRef(new QuerySet(this, descriptor));
     }
     ResultOrError<Ref<RenderPipelineBase>> Device::CreateRenderPipelineImpl(
-        const RenderPipelineDescriptor* descriptor) {
+        const RenderPipelineDescriptor2* descriptor) {
         return AcquireRef(new RenderPipeline(this, descriptor));
     }
     ResultOrError<Ref<SamplerBase>> Device::CreateSamplerImpl(const SamplerDescriptor* descriptor) {
diff --git a/src/dawn_native/null/DeviceNull.h b/src/dawn_native/null/DeviceNull.h
index 75680db..815d4a0 100644
--- a/src/dawn_native/null/DeviceNull.h
+++ b/src/dawn_native/null/DeviceNull.h
@@ -135,7 +135,7 @@
         ResultOrError<Ref<QuerySetBase>> CreateQuerySetImpl(
             const QuerySetDescriptor* descriptor) override;
         ResultOrError<Ref<RenderPipelineBase>> CreateRenderPipelineImpl(
-            const RenderPipelineDescriptor* descriptor) override;
+            const RenderPipelineDescriptor2* descriptor) override;
         ResultOrError<Ref<SamplerBase>> CreateSamplerImpl(
             const SamplerDescriptor* descriptor) override;
         ResultOrError<Ref<ShaderModuleBase>> CreateShaderModuleImpl(
diff --git a/src/dawn_native/opengl/DeviceGL.cpp b/src/dawn_native/opengl/DeviceGL.cpp
index 994590e..a1248d8 100644
--- a/src/dawn_native/opengl/DeviceGL.cpp
+++ b/src/dawn_native/opengl/DeviceGL.cpp
@@ -140,7 +140,7 @@
         return AcquireRef(new QuerySet(this, descriptor));
     }
     ResultOrError<Ref<RenderPipelineBase>> Device::CreateRenderPipelineImpl(
-        const RenderPipelineDescriptor* descriptor) {
+        const RenderPipelineDescriptor2* descriptor) {
         return AcquireRef(new RenderPipeline(this, descriptor));
     }
     ResultOrError<Ref<SamplerBase>> Device::CreateSamplerImpl(const SamplerDescriptor* descriptor) {
diff --git a/src/dawn_native/opengl/DeviceGL.h b/src/dawn_native/opengl/DeviceGL.h
index 7069cae..232fd53 100644
--- a/src/dawn_native/opengl/DeviceGL.h
+++ b/src/dawn_native/opengl/DeviceGL.h
@@ -90,7 +90,7 @@
         ResultOrError<Ref<QuerySetBase>> CreateQuerySetImpl(
             const QuerySetDescriptor* descriptor) override;
         ResultOrError<Ref<RenderPipelineBase>> CreateRenderPipelineImpl(
-            const RenderPipelineDescriptor* descriptor) override;
+            const RenderPipelineDescriptor2* descriptor) override;
         ResultOrError<Ref<SamplerBase>> CreateSamplerImpl(
             const SamplerDescriptor* descriptor) override;
         ResultOrError<Ref<ShaderModuleBase>> CreateShaderModuleImpl(
diff --git a/src/dawn_native/opengl/RenderPipelineGL.cpp b/src/dawn_native/opengl/RenderPipelineGL.cpp
index c5e9805..3c153fb 100644
--- a/src/dawn_native/opengl/RenderPipelineGL.cpp
+++ b/src/dawn_native/opengl/RenderPipelineGL.cpp
@@ -210,16 +210,16 @@
 
     }  // anonymous namespace
 
-    RenderPipeline::RenderPipeline(Device* device, const RenderPipelineDescriptor* descriptor)
+    RenderPipeline::RenderPipeline(Device* device, const RenderPipelineDescriptor2* descriptor)
         : RenderPipelineBase(device, descriptor),
           mVertexArrayObject(0),
           mGlPrimitiveTopology(GLPrimitiveTopology(GetPrimitiveTopology())) {
         PerStage<const ShaderModule*> modules(nullptr);
-        modules[SingleShaderStage::Vertex] = ToBackend(descriptor->vertexStage.module);
-        modules[SingleShaderStage::Fragment] = ToBackend(descriptor->fragmentStage->module);
+        modules[SingleShaderStage::Vertex] = ToBackend(descriptor->vertex.module);
+        modules[SingleShaderStage::Fragment] = ToBackend(descriptor->fragment->module);
 
         PipelineGL::Initialize(device->gl, ToBackend(GetLayout()), GetAllStages());
-        CreateVAOForVertexState(descriptor->vertexState);
+        CreateVAOForVertexState();
     }
 
     RenderPipeline::~RenderPipeline() {
@@ -238,7 +238,7 @@
         return mAttributesUsingVertexBuffer[slot];
     }
 
-    void RenderPipeline::CreateVAOForVertexState(const VertexStateDescriptor* vertexState) {
+    void RenderPipeline::CreateVAOForVertexState() {
         const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
 
         gl.GenVertexArrays(1, &mVertexArrayObject);
diff --git a/src/dawn_native/opengl/RenderPipelineGL.h b/src/dawn_native/opengl/RenderPipelineGL.h
index e15c864..0dc7f32 100644
--- a/src/dawn_native/opengl/RenderPipelineGL.h
+++ b/src/dawn_native/opengl/RenderPipelineGL.h
@@ -29,7 +29,7 @@
 
     class RenderPipeline final : public RenderPipelineBase, public PipelineGL {
       public:
-        RenderPipeline(Device* device, const RenderPipelineDescriptor* descriptor);
+        RenderPipeline(Device* device, const RenderPipelineDescriptor2* descriptor);
 
         GLenum GetGLPrimitiveTopology() const;
         ityp::bitset<VertexAttributeLocation, kMaxVertexAttributes> GetAttributesUsingVertexBuffer(
@@ -39,7 +39,7 @@
 
       private:
         ~RenderPipeline() override;
-        void CreateVAOForVertexState(const VertexStateDescriptor* vertexState);
+        void CreateVAOForVertexState();
 
         // TODO(yunchao.he@intel.com): vao need to be deduplicated between pipelines.
         GLuint mVertexArrayObject;
diff --git a/src/dawn_native/vulkan/DeviceVk.cpp b/src/dawn_native/vulkan/DeviceVk.cpp
index aa6d85d..2c9d32f 100644
--- a/src/dawn_native/vulkan/DeviceVk.cpp
+++ b/src/dawn_native/vulkan/DeviceVk.cpp
@@ -131,7 +131,7 @@
         return QuerySet::Create(this, descriptor);
     }
     ResultOrError<Ref<RenderPipelineBase>> Device::CreateRenderPipelineImpl(
-        const RenderPipelineDescriptor* descriptor) {
+        const RenderPipelineDescriptor2* descriptor) {
         return RenderPipeline::Create(this, descriptor);
     }
     ResultOrError<Ref<SamplerBase>> Device::CreateSamplerImpl(const SamplerDescriptor* descriptor) {
diff --git a/src/dawn_native/vulkan/DeviceVk.h b/src/dawn_native/vulkan/DeviceVk.h
index 870dc47..3e4bff1 100644
--- a/src/dawn_native/vulkan/DeviceVk.h
+++ b/src/dawn_native/vulkan/DeviceVk.h
@@ -127,7 +127,7 @@
         ResultOrError<Ref<QuerySetBase>> CreateQuerySetImpl(
             const QuerySetDescriptor* descriptor) override;
         ResultOrError<Ref<RenderPipelineBase>> CreateRenderPipelineImpl(
-            const RenderPipelineDescriptor* descriptor) override;
+            const RenderPipelineDescriptor2* descriptor) override;
         ResultOrError<Ref<SamplerBase>> CreateSamplerImpl(
             const SamplerDescriptor* descriptor) override;
         ResultOrError<Ref<ShaderModuleBase>> CreateShaderModuleImpl(
diff --git a/src/dawn_native/vulkan/RenderPipelineVk.cpp b/src/dawn_native/vulkan/RenderPipelineVk.cpp
index 105e640..bbb4f8ee 100644
--- a/src/dawn_native/vulkan/RenderPipelineVk.cpp
+++ b/src/dawn_native/vulkan/RenderPipelineVk.cpp
@@ -321,13 +321,13 @@
     // static
     ResultOrError<Ref<RenderPipeline>> RenderPipeline::Create(
         Device* device,
-        const RenderPipelineDescriptor* descriptor) {
+        const RenderPipelineDescriptor2* descriptor) {
         Ref<RenderPipeline> pipeline = AcquireRef(new RenderPipeline(device, descriptor));
         DAWN_TRY(pipeline->Initialize(descriptor));
         return pipeline;
     }
 
-    MaybeError RenderPipeline::Initialize(const RenderPipelineDescriptor* descriptor) {
+    MaybeError RenderPipeline::Initialize(const RenderPipelineDescriptor2* descriptor) {
         Device* device = ToBackend(GetDevice());
 
         VkPipelineShaderStageCreateInfo shaderStages[2];
@@ -337,16 +337,16 @@
             shaderStages[0].flags = 0;
             shaderStages[0].stage = VK_SHADER_STAGE_VERTEX_BIT;
             shaderStages[0].pSpecializationInfo = nullptr;
-            shaderStages[0].module = ToBackend(descriptor->vertexStage.module)->GetHandle();
-            shaderStages[0].pName = descriptor->vertexStage.entryPoint;
+            shaderStages[0].module = ToBackend(descriptor->vertex.module)->GetHandle();
+            shaderStages[0].pName = descriptor->vertex.entryPoint;
 
             shaderStages[1].sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
             shaderStages[1].pNext = nullptr;
             shaderStages[1].flags = 0;
             shaderStages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT;
             shaderStages[1].pSpecializationInfo = nullptr;
-            shaderStages[1].module = ToBackend(descriptor->fragmentStage->module)->GetHandle();
-            shaderStages[1].pName = descriptor->fragmentStage->entryPoint;
+            shaderStages[1].module = ToBackend(descriptor->fragment->module)->GetHandle();
+            shaderStages[1].pName = descriptor->fragment->entryPoint;
         }
 
         PipelineVertexInputStateCreateInfoTemporaryAllocations tempAllocations;
@@ -411,7 +411,7 @@
         ASSERT(multisample.rasterizationSamples <= 32);
         VkSampleMask sampleMask = GetSampleMask();
         multisample.pSampleMask = &sampleMask;
-        multisample.alphaToCoverageEnable = descriptor->alphaToCoverageEnabled;
+        multisample.alphaToCoverageEnable = IsAlphaToCoverageEnabled();
         multisample.alphaToOneEnable = VK_FALSE;
 
         VkPipelineDepthStencilStateCreateInfo depthStencilState =
diff --git a/src/dawn_native/vulkan/RenderPipelineVk.h b/src/dawn_native/vulkan/RenderPipelineVk.h
index 7dfc468..be61fa2 100644
--- a/src/dawn_native/vulkan/RenderPipelineVk.h
+++ b/src/dawn_native/vulkan/RenderPipelineVk.h
@@ -28,14 +28,14 @@
       public:
         static ResultOrError<Ref<RenderPipeline>> Create(
             Device* device,
-            const RenderPipelineDescriptor* descriptor);
+            const RenderPipelineDescriptor2* descriptor);
 
         VkPipeline GetHandle() const;
 
       private:
         ~RenderPipeline() override;
         using RenderPipelineBase::RenderPipelineBase;
-        MaybeError Initialize(const RenderPipelineDescriptor* descriptor);
+        MaybeError Initialize(const RenderPipelineDescriptor2* descriptor);
 
         struct PipelineVertexInputStateCreateInfoTemporaryAllocations {
             std::array<VkVertexInputBindingDescription, kMaxVertexBuffers> bindings;
diff --git a/src/tests/unittests/validation/RenderPipelineValidationTests.cpp b/src/tests/unittests/validation/RenderPipelineValidationTests.cpp
index 08b0301..0dd9bc0 100644
--- a/src/tests/unittests/validation/RenderPipelineValidationTests.cpp
+++ b/src/tests/unittests/validation/RenderPipelineValidationTests.cpp
@@ -59,7 +59,7 @@
         descriptor.vertexStage.module = vsModule;
         descriptor.cFragmentStage.module = fsModule;
 
-        device.CreateRenderPipeline(&descriptor);
+        EXPECT_DEPRECATION_WARNING(device.CreateRenderPipeline(&descriptor));
     }
     {
         // Vertex input should be optional
@@ -68,7 +68,7 @@
         descriptor.cFragmentStage.module = fsModule;
         descriptor.vertexState = nullptr;
 
-        device.CreateRenderPipeline(&descriptor);
+        EXPECT_DEPRECATION_WARNING(device.CreateRenderPipeline(&descriptor));
     }
     {
         // Rasterization state should be optional
@@ -76,7 +76,7 @@
         descriptor.vertexStage.module = vsModule;
         descriptor.cFragmentStage.module = fsModule;
         descriptor.rasterizationState = nullptr;
-        device.CreateRenderPipeline(&descriptor);
+        EXPECT_DEPRECATION_WARNING(device.CreateRenderPipeline(&descriptor));
     }
 }