// Copyright 2017 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
//    list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
//    this list of conditions and the following disclaimer in the documentation
//    and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
//    contributors may be used to endorse or promote products derived from
//    this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "src/dawn/native/RenderPipeline.h"

#include <algorithm>
#include <cmath>

#include "dawn/native/ObjectType_autogen.h"
#include "dawn/native/ValidationUtils_autogen.h"
#include "src/dawn/common/Enumerator.h"
#include "src/dawn/common/ityp_array.h"
#include "src/dawn/common/ityp_bitset.h"
#include "src/dawn/native/Adapter.h"
#include "src/dawn/native/ChainUtils.h"
#include "src/dawn/native/CommandValidation.h"
#include "src/dawn/native/Commands.h"
#include "src/dawn/native/Device.h"
#include "src/dawn/native/InternalPipelineStore.h"
#include "src/dawn/native/ObjectContentHasher.h"
#include "src/dawn/native/ValidationUtils.h"
#include "src/utils/compiler.h"
#include "src/utils/span.h"

namespace dawn::native {

static constexpr ityp::array<wgpu::VertexFormat, VertexFormatInfo, 42> sVertexFormatTable =
    []() constexpr {
        ityp::array<wgpu::VertexFormat, VertexFormatInfo, 42> table{};

        // clang-format off
        table[wgpu::VertexFormat::Uint8          ] = { 1, 1, VertexFormatBaseType::Uint };
        table[wgpu::VertexFormat::Uint8x2        ] = { 2, 2, VertexFormatBaseType::Uint };
        table[wgpu::VertexFormat::Uint8x4        ] = { 4, 4, VertexFormatBaseType::Uint };
        table[wgpu::VertexFormat::Sint8          ] = { 1, 1, VertexFormatBaseType::Sint };
        table[wgpu::VertexFormat::Sint8x2        ] = { 2, 2, VertexFormatBaseType::Sint };
        table[wgpu::VertexFormat::Sint8x4        ] = { 4, 4, VertexFormatBaseType::Sint };
        table[wgpu::VertexFormat::Unorm8         ] = { 1, 1, VertexFormatBaseType::Float};
        table[wgpu::VertexFormat::Unorm8x2       ] = { 2, 2, VertexFormatBaseType::Float};
        table[wgpu::VertexFormat::Unorm8x4       ] = { 4, 4, VertexFormatBaseType::Float};
        table[wgpu::VertexFormat::Snorm8         ] = { 1, 1, VertexFormatBaseType::Float};
        table[wgpu::VertexFormat::Snorm8x2       ] = { 2, 2, VertexFormatBaseType::Float};
        table[wgpu::VertexFormat::Snorm8x4       ] = { 4, 4, VertexFormatBaseType::Float};

        table[wgpu::VertexFormat::Uint16         ] = { 2, 1, VertexFormatBaseType::Uint };
        table[wgpu::VertexFormat::Uint16x2       ] = { 4, 2, VertexFormatBaseType::Uint };
        table[wgpu::VertexFormat::Uint16x4       ] = { 8, 4, VertexFormatBaseType::Uint };
        table[wgpu::VertexFormat::Sint16         ] = { 2, 1, VertexFormatBaseType::Sint };
        table[wgpu::VertexFormat::Sint16x2       ] = { 4, 2, VertexFormatBaseType::Sint };
        table[wgpu::VertexFormat::Sint16x4       ] = { 8, 4, VertexFormatBaseType::Sint };
        table[wgpu::VertexFormat::Unorm16        ] = { 2, 1, VertexFormatBaseType::Float};
        table[wgpu::VertexFormat::Unorm16x2      ] = { 4, 2, VertexFormatBaseType::Float};
        table[wgpu::VertexFormat::Unorm16x4      ] = { 8, 4, VertexFormatBaseType::Float};
        table[wgpu::VertexFormat::Snorm16        ] = { 2, 1, VertexFormatBaseType::Float};
        table[wgpu::VertexFormat::Snorm16x2      ] = { 4, 2, VertexFormatBaseType::Float};
        table[wgpu::VertexFormat::Snorm16x4      ] = { 8, 4, VertexFormatBaseType::Float};
        table[wgpu::VertexFormat::Float16        ] = { 2, 1, VertexFormatBaseType::Float};
        table[wgpu::VertexFormat::Float16x2      ] = { 4, 2, VertexFormatBaseType::Float};
        table[wgpu::VertexFormat::Float16x4      ] = { 8, 4, VertexFormatBaseType::Float};

        table[wgpu::VertexFormat::Float32        ] = { 4, 1, VertexFormatBaseType::Float};
        table[wgpu::VertexFormat::Float32x2      ] = { 8, 2, VertexFormatBaseType::Float};
        table[wgpu::VertexFormat::Float32x3      ] = {12, 3, VertexFormatBaseType::Float};
        table[wgpu::VertexFormat::Float32x4      ] = {16, 4, VertexFormatBaseType::Float};
        table[wgpu::VertexFormat::Uint32         ] = { 4, 1, VertexFormatBaseType::Uint };
        table[wgpu::VertexFormat::Uint32x2       ] = { 8, 2, VertexFormatBaseType::Uint };
        table[wgpu::VertexFormat::Uint32x3       ] = {12, 3, VertexFormatBaseType::Uint };
        table[wgpu::VertexFormat::Uint32x4       ] = {16, 4, VertexFormatBaseType::Uint };
        table[wgpu::VertexFormat::Sint32         ] = { 4, 1, VertexFormatBaseType::Sint };
        table[wgpu::VertexFormat::Sint32x2       ] = { 8, 2, VertexFormatBaseType::Sint };
        table[wgpu::VertexFormat::Sint32x3       ] = {12, 3, VertexFormatBaseType::Sint };
        table[wgpu::VertexFormat::Sint32x4       ] = {16, 4, VertexFormatBaseType::Sint };
        table[wgpu::VertexFormat::Unorm10_10_10_2] = { 4, 4, VertexFormatBaseType::Float};
        table[wgpu::VertexFormat::Unorm8x4BGRA   ] = { 4, 4, VertexFormatBaseType::Float};
        // clang-format on

        return table;
    }();

const VertexFormatInfo& GetVertexFormatInfo(wgpu::VertexFormat format) {
    DAWN_CHECK(static_cast<uint32_t>(format) < static_cast<uint32_t>(sVertexFormatTable.size()));
    DAWN_CHECK(static_cast<uint32_t>(format) != 0u);
    return sVertexFormatTable[format];
}

// Helper functions
namespace {
MaybeError ValidateVertexAttribute(DeviceBase* device,
                                   const VertexAttribute& attribute,
                                   const EntryPointMetadata& metadata,
                                   uint64_t vertexBufferStride,
                                   VertexAttributeMask* attributesSetMask) {
    DAWN_TRY(ValidateVertexFormat(attribute.format));
    const VertexFormatInfo& formatInfo = GetVertexFormatInfo(attribute.format);

    uint32_t maxVertexAttributes = device->GetLimits().v1.maxVertexAttributes;
    DAWN_INVALID_IF(
        attribute.shaderLocation >= maxVertexAttributes,
        "Attribute shader location (%u) exceeds the maximum number of vertex attributes "
        "(%u).",
        attribute.shaderLocation, maxVertexAttributes);

    VertexAttributeLocation location(static_cast<uint8_t>(attribute.shaderLocation));

    // No underflow is possible because the max vertex format size is smaller than
    // kMaxVertexBufferArrayStride.
    DAWN_CHECK(kMaxVertexBufferArrayStride >= formatInfo.byteSize);
    DAWN_INVALID_IF(attribute.offset > kMaxVertexBufferArrayStride - formatInfo.byteSize,
                    "Attribute offset (%u) + format size (%u for %s) must be <= the maximum vertex "
                    "buffer stride (%u). Offsets larger than the maximum vertex buffer stride are "
                    "accommodated by setting buffer offsets when calling setVertexBuffer, which "
                    "the attribute offset is added to.",
                    attribute.offset, formatInfo.byteSize, attribute.format,
                    kMaxVertexBufferArrayStride);

    // No overflow is possible because the offset is already validated to be less
    // than kMaxVertexBufferArrayStride.
    DAWN_CHECK(attribute.offset < kMaxVertexBufferArrayStride);
    DAWN_INVALID_IF(
        vertexBufferStride > 0 && attribute.offset + formatInfo.byteSize > vertexBufferStride,
        "Attribute offset (%u) + format size (%u for %s) must be <= the vertex buffer stride (%u). "
        "Offsets larger than the vertex buffer stride are accommodated by setting buffer offsets "
        "when calling setVertexBuffer, which the attribute offset is added to.",
        attribute.offset, formatInfo.byteSize, attribute.format, vertexBufferStride);

    DAWN_INVALID_IF(attribute.offset % std::min(4u, formatInfo.byteSize) != 0,
                    "Attribute offset (%u) in not a multiple of %u.", attribute.offset,
                    std::min(4u, formatInfo.byteSize));

    DAWN_INVALID_IF(metadata.usedVertexInputs[location] &&
                        formatInfo.baseType != metadata.vertexInputBaseTypes[location],
                    "Attribute base type (%s for %s) does not match the shader's base type (%s) in "
                    "location (%u).",
                    formatInfo.baseType, attribute.format, metadata.vertexInputBaseTypes[location],
                    attribute.shaderLocation);

    DAWN_INVALID_IF((*attributesSetMask)[location],
                    "Attribute shader location (%u) is used more than once.",
                    attribute.shaderLocation);

    attributesSetMask->set(location);
    return {};
}

MaybeError ValidateVertexBufferLayout(DeviceBase* device,
                                      const VertexBufferLayout& buffer,
                                      const EntryPointMetadata& metadata,
                                      VertexAttributeMask* attributesSetMask) {
    DAWN_TRY(ValidateVertexStepMode(buffer.stepMode));
    DAWN_INVALID_IF(buffer.arrayStride > kMaxVertexBufferArrayStride,
                    "Vertex buffer arrayStride (%u) is larger than the maximum array stride (%u).",
                    buffer.arrayStride, kMaxVertexBufferArrayStride);

    DAWN_INVALID_IF(buffer.arrayStride % 4 != 0,
                    "Vertex buffer arrayStride (%u) is not a multiple of 4.", buffer.arrayStride);

    for (auto [i, attribute] : Enumerate(buffer.attributes)) {
        DAWN_TRY_CONTEXT(ValidateVertexAttribute(device, attribute, metadata, buffer.arrayStride,
                                                 attributesSetMask),
                         "validating attributes[%u].", i);
    }

    return {};
}

ResultOrError<ShaderModuleEntryPoint> ValidateVertexState(
    DeviceBase* device,
    const VertexState* descriptor,
    const PipelineLayoutBase* layout,
    wgpu::PrimitiveTopology primitiveTopology) {
    DAWN_INVALID_IF(descriptor->nextInChain != nullptr, "nextInChain must be nullptr.");

    const CombinedLimits& limits = device->GetLimits();

    auto maxVertexBuffers = VertexBufferSlot{static_cast<uint8_t>(limits.v1.maxVertexBuffers)};
    DAWN_INVALID_IF(
        descriptor->buffers.size() > maxVertexBuffers,
        "Vertex buffer count (%u) exceeds the maximum number of vertex buffers (%u).%s",
        descriptor->buffers.size(), maxVertexBuffers,
        DAWN_INCREASE_LIMIT_MESSAGE(device->GetAdapter()->GetLimits().v1, maxVertexBuffers,
                                    uint8_t{descriptor->buffers.size()}));

    ShaderModuleEntryPoint entryPoint;
    DAWN_TRY_ASSIGN_CONTEXT(
        entryPoint,
        ValidateProgrammableStage(device, descriptor->module, descriptor->entryPoint,
                                  descriptor->constants, layout, SingleShaderStage::Vertex),
        "validating vertex stage (%s, entryPoint: %s).", descriptor->module,
        descriptor->entryPoint);
    const EntryPointMetadata& vertexMetadata = descriptor->module->GetEntryPoint(entryPoint.name);
    if (primitiveTopology == wgpu::PrimitiveTopology::PointList) {
        DAWN_INVALID_IF(
            vertexMetadata.totalInterStageShaderVariables + 1 >
                limits.v1.maxInterStageShaderVariables,
            "Total vertex output variables count (%u) exceeds the maximum (%u) when primitive "
            "topology is %s as another variable is implicitly used for the point size.",
            vertexMetadata.totalInterStageShaderVariables,
            limits.v1.maxInterStageShaderVariables - 1, primitiveTopology);
    }

    VertexAttributeMask attributesSetMask;
    uint32_t totalAttributesNum = 0;
    for (auto [i, buffer] : Enumerate(descriptor->buffers)) {
        DAWN_TRY_CONTEXT(
            ValidateVertexBufferLayout(device, buffer, vertexMetadata, &attributesSetMask),
            "validating buffers[%u].", i);
        totalAttributesNum += static_cast<uint32_t>(buffer.attributes.size());
    }

    if (device->IsCompatibilityMode() &&
        (vertexMetadata.usesVertexIndex || vertexMetadata.usesInstanceIndex)) {
        uint32_t totalEffectiveAttributesNum = totalAttributesNum +
                                               (vertexMetadata.usesVertexIndex ? 1 : 0) +
                                               (vertexMetadata.usesInstanceIndex ? 1 : 0);
        DAWN_INVALID_IF(totalEffectiveAttributesNum > limits.v1.maxVertexAttributes,
                        "Attribute count (%u) exceeds the maximum number of attributes (%u) as "
                        "@builtin(vertex_index) and @builtin(instance_index) each use an attribute "
                        "in compatibility mode.",
                        totalEffectiveAttributesNum, limits.v1.maxVertexAttributes);
    }

    // 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.
    DAWN_CHECK(totalAttributesNum <= kMaxVertexAttributes);

    // Validate that attributes used by the VertexState are in the shader using bitmask operations
    // but try to be helpful by finding one missing attribute to surface in the error message
    if (!IsSubset(vertexMetadata.usedVertexInputs, attributesSetMask)) {
        const VertexAttributeMask missingAttributes =
            vertexMetadata.usedVertexInputs & ~attributesSetMask;
        DAWN_CHECK(missingAttributes.any());

        VertexAttributeLocation firstMissing =
            GetHighestBitIndexPlusOne(missingAttributes).MinusOne();
        return DAWN_VALIDATION_ERROR(
            "Vertex attribute slot %u used in (%s, %s) is not present in the "
            "VertexState.",
            uint8_t(firstMissing), descriptor->module, entryPoint);
    }

    return entryPoint;
}

MaybeError ValidatePrimitiveState(const DeviceBase* device, const PrimitiveState* rawDescriptor) {
    UnpackedPtr<PrimitiveState> descriptor;
    DAWN_TRY_ASSIGN(descriptor, ValidateAndUnpack(rawDescriptor));
    DAWN_INVALID_IF(descriptor->unclippedDepth && !device->HasFeature(Feature::DepthClipControl),
                    "%s is not supported", wgpu::FeatureName::DepthClipControl);
    DAWN_TRY(ValidatePrimitiveTopology(descriptor->topology));
    DAWN_TRY(ValidateIndexFormat(descriptor->stripIndexFormat));
    DAWN_TRY(ValidateFrontFace(descriptor->frontFace));
    DAWN_TRY(ValidateCullMode(descriptor->cullMode));

    // Pipeline descriptors must have stripIndexFormat == undefined if they are using
    // non-strip topologies.
    if (!IsStripPrimitiveTopology(descriptor->topology)) {
        DAWN_INVALID_IF(descriptor->stripIndexFormat != wgpu::IndexFormat::Undefined,
                        "StripIndexFormat (%s) is not undefined when using a non-strip primitive "
                        "topology (%s).",
                        descriptor->stripIndexFormat, descriptor->topology);
    }

    return {};
}

MaybeError ValidateStencilFaceUnused(StencilFaceState face) {
    DAWN_INVALID_IF((face.compare != wgpu::CompareFunction::Always) &&
                        (face.compare != wgpu::CompareFunction::Undefined),
                    "compare (%s) is defined and not %s.", face.compare,
                    wgpu::CompareFunction::Always);
    DAWN_INVALID_IF((face.failOp != wgpu::StencilOperation::Keep) &&
                        (face.failOp != wgpu::StencilOperation::Undefined),
                    "failOp (%s) is defined and not %s.", face.failOp,
                    wgpu::StencilOperation::Keep);
    DAWN_INVALID_IF((face.depthFailOp != wgpu::StencilOperation::Keep) &&
                        (face.depthFailOp != wgpu::StencilOperation::Undefined),
                    "depthFailOp (%s) is defined and not %s.", face.depthFailOp,
                    wgpu::StencilOperation::Keep);
    DAWN_INVALID_IF((face.passOp != wgpu::StencilOperation::Keep) &&
                        (face.passOp != wgpu::StencilOperation::Undefined),
                    "passOp (%s) is defined and not %s.", face.passOp,
                    wgpu::StencilOperation::Keep);
    return {};
}

MaybeError ValidateDepthStencilState(const DeviceBase* device,
                                     const DepthStencilState* descriptor,
                                     const wgpu::PrimitiveTopology topology) {
    DAWN_TRY_CONTEXT(ValidateCompareFunction(descriptor->depthCompare),
                     "validating depth compare function");
    DAWN_TRY_CONTEXT(ValidateCompareFunction(descriptor->stencilFront.compare),
                     "validating stencil front compare function");
    DAWN_TRY_CONTEXT(ValidateStencilOperation(descriptor->stencilFront.failOp),
                     "validating stencil front fail operation");
    DAWN_TRY_CONTEXT(ValidateStencilOperation(descriptor->stencilFront.depthFailOp),
                     "validating stencil front depth fail operation");
    DAWN_TRY_CONTEXT(ValidateStencilOperation(descriptor->stencilFront.passOp),
                     "validating stencil front pass operation");
    DAWN_TRY_CONTEXT(ValidateCompareFunction(descriptor->stencilBack.compare),
                     "validating stencil back compare function");
    DAWN_TRY_CONTEXT(ValidateStencilOperation(descriptor->stencilBack.failOp),
                     "validating stencil back fail operation");
    DAWN_TRY_CONTEXT(ValidateStencilOperation(descriptor->stencilBack.depthFailOp),
                     "validating stencil back depth fail operation");
    DAWN_TRY_CONTEXT(ValidateStencilOperation(descriptor->stencilBack.passOp),
                     "validating stencil back pass operation");

    const Format* format;
    DAWN_TRY_ASSIGN(format, device->GetInternalFormat(descriptor->format));
    DAWN_INVALID_IF(!format->HasDepthOrStencil() || !format->IsRenderable(),
                    "Depth stencil format (%s) is not depth-stencil renderable.",
                    descriptor->format);

    DAWN_TRY(ValidateFloat("depthBiasSlopeScale", descriptor->depthBiasSlopeScale));
    DAWN_TRY(ValidateFloat("depthBiasClamp", descriptor->depthBiasClamp));

    DAWN_INVALID_IF(device->IsCompatibilityMode() && descriptor->depthBiasClamp != 0.0f,
                    "depthBiasClamp (%f) is not zero as required in compatibility mode.",
                    descriptor->depthBiasClamp);

    DAWN_INVALID_IF(
        format->HasDepth() && descriptor->depthCompare == wgpu::CompareFunction::Undefined &&
            (descriptor->depthWriteEnabled == wgpu::OptionalBool::True ||
             descriptor->stencilFront.depthFailOp != wgpu::StencilOperation::Keep ||
             descriptor->stencilBack.depthFailOp != wgpu::StencilOperation::Keep),
        "Depth stencil format (%s) has a depth aspect and depthCompare is %s while it's actually "
        "used by depthWriteEnabled (%s), or stencil front depth fail operation (%s), or "
        "stencil back depth fail operation (%s).",
        descriptor->format, wgpu::CompareFunction::Undefined, descriptor->depthWriteEnabled,
        descriptor->stencilFront.depthFailOp, descriptor->stencilBack.depthFailOp);

    DAWN_INVALID_IF(
        format->HasDepth() && descriptor->depthWriteEnabled == wgpu::OptionalBool::Undefined,
        "Depth stencil format (%s) has a depth aspect and depthWriteEnabled is undefined.",
        descriptor->format);

    DAWN_INVALID_IF(
        !format->HasDepth() && descriptor->depthCompare != wgpu::CompareFunction::Always &&
            descriptor->depthCompare != wgpu::CompareFunction::Undefined,
        "Depth stencil format (%s) doesn't have depth aspect while depthCompare (%s) is "
        "neither %s nor %s.",
        descriptor->format, descriptor->depthCompare, wgpu::CompareFunction::Always,
        wgpu::CompareFunction::Undefined);

    DAWN_INVALID_IF(
        !format->HasDepth() && descriptor->depthWriteEnabled == wgpu::OptionalBool::True,
        "Depth stencil format (%s) doesn't have depth aspect while depthWriteEnabled (%s) "
        "is true.",
        descriptor->format, descriptor->depthWriteEnabled);

    if (!format->HasStencil()) {
        DAWN_TRY_CONTEXT(ValidateStencilFaceUnused(descriptor->stencilFront),
                         "validating that stencilFront doesn't use stencil when the depth-stencil "
                         "format (%s) doesn't have a stencil aspect.",
                         descriptor->format);
        DAWN_TRY_CONTEXT(ValidateStencilFaceUnused(descriptor->stencilBack),
                         "validating that stencilBack doesn't use stencil when the depth-stencil "
                         "format (%s) doesn't have a stencil aspect.",
                         descriptor->format);
    }

    switch (topology) {
        case wgpu::PrimitiveTopology::PointList:
        case wgpu::PrimitiveTopology::LineList:
        case wgpu::PrimitiveTopology::LineStrip:
            DAWN_INVALID_IF(descriptor->depthBias != 0, "depthBias must be 0 when using %s.",
                            topology);
            DAWN_INVALID_IF(descriptor->depthBiasSlopeScale != 0,
                            "depthBiasSlopeScale must be 0 when using %s.", topology);
            DAWN_INVALID_IF(descriptor->depthBiasClamp != 0,
                            "depthBiasClamp must be 0 when using using %s.", topology);
            break;
        case wgpu::PrimitiveTopology::Undefined:
            // Default is TriangleList.
        case wgpu::PrimitiveTopology::TriangleList:
        case wgpu::PrimitiveTopology::TriangleStrip:
            break;
    }

    return {};
}

MaybeError ValidateMultisampleState(const DeviceBase* device, const MultisampleState* descriptor) {
    DAWN_INVALID_IF(!IsValidSampleCount(descriptor->count),
                    "Multisample count (%u) is not supported.", descriptor->count);

    DAWN_INVALID_IF(descriptor->alphaToCoverageEnabled && descriptor->count <= 1,
                    "Multisample count (%u) must be > 1 when alphaToCoverage is enabled.",
                    descriptor->count);

    return {};
}

MaybeError ValidateBlendComponent(BlendComponent blendComponent, bool dualSourceBlendingEnabled) {
    if (!dualSourceBlendingEnabled) {
        DAWN_INVALID_IF(blendComponent.srcFactor == wgpu::BlendFactor::Src1 ||
                            blendComponent.srcFactor == wgpu::BlendFactor::OneMinusSrc1 ||
                            blendComponent.srcFactor == wgpu::BlendFactor::Src1Alpha ||
                            blendComponent.srcFactor == wgpu::BlendFactor::OneMinusSrc1Alpha,
                        "Source blend factor is %s while dualSourceBlending is not enabled.",
                        blendComponent.srcFactor);

        DAWN_INVALID_IF(blendComponent.dstFactor == wgpu::BlendFactor::Src1 ||
                            blendComponent.dstFactor == wgpu::BlendFactor::OneMinusSrc1 ||
                            blendComponent.dstFactor == wgpu::BlendFactor::Src1Alpha ||
                            blendComponent.dstFactor == wgpu::BlendFactor::OneMinusSrc1Alpha,
                        "Destination blend factor is %s while dualSourceBlending is not enabled.",
                        blendComponent.dstFactor);
    }

    if (blendComponent.operation == wgpu::BlendOperation::Min ||
        blendComponent.operation == wgpu::BlendOperation::Max) {
        DAWN_INVALID_IF(
            (blendComponent.srcFactor != wgpu::BlendFactor::One) &&
                (blendComponent.srcFactor != wgpu::BlendFactor::Undefined),
            "Source blend factor (%s) is defined and not %s when blend operation is %s.",
            blendComponent.srcFactor, wgpu::BlendFactor::One, blendComponent.operation);
        DAWN_INVALID_IF(
            (blendComponent.dstFactor != wgpu::BlendFactor::One) &&
                (blendComponent.dstFactor != wgpu::BlendFactor::Undefined),
            "Destination blend factor (%s) is defined and not %s when blend operation is %s.",
            blendComponent.dstFactor, wgpu::BlendFactor::One, blendComponent.operation);
    }

    return {};
}

MaybeError ValidateBlendState(DeviceBase* device, const BlendState* descriptor) {
    DAWN_TRY(ValidateBlendOperation(descriptor->alpha.operation));
    DAWN_TRY(ValidateBlendFactor(descriptor->alpha.srcFactor));
    DAWN_TRY(ValidateBlendFactor(descriptor->alpha.dstFactor));
    DAWN_TRY(ValidateBlendOperation(descriptor->color.operation));
    DAWN_TRY(ValidateBlendFactor(descriptor->color.srcFactor));
    DAWN_TRY(ValidateBlendFactor(descriptor->color.dstFactor));

    bool dualSourceBlendingEnabled = device->HasFeature(Feature::DualSourceBlending);
    DAWN_TRY(ValidateBlendComponent(descriptor->alpha, dualSourceBlendingEnabled));
    DAWN_TRY(ValidateBlendComponent(descriptor->color, dualSourceBlendingEnabled));

    return {};
}

bool BlendFactorContainsSrcAlpha(wgpu::BlendFactor blendFactor) {
    return blendFactor == wgpu::BlendFactor::SrcAlpha ||
           blendFactor == wgpu::BlendFactor::OneMinusSrcAlpha ||
           blendFactor == wgpu::BlendFactor::SrcAlphaSaturated ||
           blendFactor == wgpu::BlendFactor::Src1Alpha ||
           blendFactor == wgpu::BlendFactor::OneMinusSrc1Alpha;
}

bool BlendFactorContainsSrc1(wgpu::BlendFactor blendFactor) {
    return blendFactor == wgpu::BlendFactor::Src1 ||
           blendFactor == wgpu::BlendFactor::OneMinusSrc1 ||
           blendFactor == wgpu::BlendFactor::Src1Alpha ||
           blendFactor == wgpu::BlendFactor::OneMinusSrc1Alpha;
}

bool BlendStateUsesBlendFactorSrc1(const BlendState& blend) {
    return BlendFactorContainsSrc1(blend.alpha.srcFactor) ||
           BlendFactorContainsSrc1(blend.alpha.dstFactor) ||
           BlendFactorContainsSrc1(blend.color.srcFactor) ||
           BlendFactorContainsSrc1(blend.color.dstFactor);
}

MaybeError ValidateColorTargetState(
    DeviceBase* device,
    const ColorTargetState& descriptor,
    const Format* format,
    bool fragmentWritten,
    const EntryPointMetadata::FragmentRenderAttachmentInfo& fragmentOutputVariable,
    const MultisampleState& multisample) {
    UnpackedPtr<ColorTargetState> unpacked;
    DAWN_TRY_ASSIGN(unpacked, ValidateAndUnpack(&descriptor));
    if (unpacked.Has<ColorTargetStateExpandResolveTextureDawn>()) {
        DAWN_INVALID_IF(!device->HasFeature(Feature::DawnLoadResolveTexture),
                        "The ColorTargetStateExpandResolveTextureDawn struct is used while the "
                        "%s feature is not enabled.",
                        ToAPI(Feature::DawnLoadResolveTexture));

        DAWN_INVALID_IF(
            multisample.count <= 1,
            "The ColorTargetStateExpandResolveTextureDawn struct is used while multisample count "
            "(%u) is not > 1.",
            multisample.count);
    }

    if (descriptor.blend) {
        DAWN_TRY_CONTEXT(ValidateBlendState(device, descriptor.blend), "validating blend state.");
    }

    DAWN_TRY(ValidateColorWriteMask(descriptor.writeMask));
    DAWN_INVALID_IF(!format->IsColor() || !format->IsRenderable(),
                    "Color format (%s) is not color renderable.", format->format);

    DAWN_INVALID_IF(descriptor.blend && !format->IsBlendable(),
                    "Blending is enabled but color format (%s) is not blendable.", format->format);

    if (!fragmentWritten) {
        DAWN_INVALID_IF(
            descriptor.writeMask != wgpu::ColorWriteMask::None,
            "Color target has no corresponding fragment stage output but writeMask (%s) is "
            "not zero.",
            descriptor.writeMask);
        return {};
    }

    DAWN_INVALID_IF(
        fragmentOutputVariable.baseType != format->GetAspectInfo(Aspect::Color).baseType,
        "Color format (%s) base type (%s) doesn't match the fragment "
        "module output type (%s).",
        format->format, format->GetAspectInfo(Aspect::Color).baseType,
        fragmentOutputVariable.baseType);

    DAWN_INVALID_IF(fragmentOutputVariable.componentCount < format->componentCount,
                    "The fragment stage has fewer output components (%u) than the color format "
                    "(%s) component count (%u).",
                    fragmentOutputVariable.componentCount, format->format, format->componentCount);

    if (descriptor.blend && fragmentOutputVariable.componentCount < 4u) {
        // No alpha channel output, make sure there's no alpha involved in the blending operation.
        DAWN_INVALID_IF(BlendFactorContainsSrcAlpha(descriptor.blend->color.srcFactor) ||
                            BlendFactorContainsSrcAlpha(descriptor.blend->color.dstFactor),
                        "Color blending srcFactor (%s) or dstFactor (%s) is reading alpha "
                        "but it is missing from fragment output.",
                        descriptor.blend->color.srcFactor, descriptor.blend->color.dstFactor);
    }

    return {};
}

MaybeError ValidateFramebufferInput(
    DeviceBase* device,
    const Format* format,
    const EntryPointMetadata::FragmentRenderAttachmentInfo& inputVar) {
    DAWN_INVALID_IF(inputVar.baseType != format->GetAspectInfo(Aspect::Color).baseType,
                    "Color format (%s) base type (%s) doesn't match the fragment "
                    "module input type (%s).",
                    format->format, format->GetAspectInfo(Aspect::Color).baseType,
                    inputVar.baseType);
    DAWN_INVALID_IF(inputVar.componentCount != format->componentCount,
                    "The fragment stage number of input components (%u) doesn't match the color "
                    "format (%s) component count (%u).",
                    inputVar.componentCount, format->format, format->componentCount);
    return {};
}

MaybeError ValidateColorTargetStatesMatch(ColorAttachmentIndex firstColorTargetIndex,
                                          const ColorTargetState* const firstColorTargetState,
                                          ColorAttachmentIndex targetIndex,
                                          const ColorTargetState* target) {
    DAWN_INVALID_IF(firstColorTargetState->writeMask != target->writeMask,
                    "targets[%u].writeMask (%s) does not match targets[%u].writeMask (%s).",
                    targetIndex, target->writeMask, firstColorTargetIndex,
                    firstColorTargetState->writeMask);
    if (!firstColorTargetState->blend) {
        DAWN_INVALID_IF(target->blend,
                        "targets[%u].blend has a blend state but targets[%u].blend does not.",
                        targetIndex, firstColorTargetIndex);
    } else {
        DAWN_INVALID_IF(!target->blend,
                        "targets[%u].blend has a blend state but targets[%u].blend does not.",
                        firstColorTargetIndex, targetIndex);

        const BlendState& currBlendState = *target->blend;
        const BlendState& firstBlendState = *firstColorTargetState->blend;

        DAWN_INVALID_IF(
            firstBlendState.color.operation != currBlendState.color.operation,
            "targets[%u].color.operation (%s) does not match targets[%u].color.operation (%s).",
            firstColorTargetIndex, firstBlendState.color.operation, targetIndex,
            currBlendState.color.operation);
        DAWN_INVALID_IF(
            firstBlendState.color.srcFactor != currBlendState.color.srcFactor,
            "targets[%u].color.srcFactor (%s) does not match targets[%u].color.srcFactor (%s).",
            firstColorTargetIndex, firstBlendState.color.srcFactor, targetIndex,
            currBlendState.color.srcFactor);
        DAWN_INVALID_IF(
            firstBlendState.color.dstFactor != currBlendState.color.dstFactor,
            "targets[%u].color.dstFactor (%s) does not match targets[%u].color.dstFactor (%s).",
            firstColorTargetIndex, firstBlendState.color.dstFactor, targetIndex,
            currBlendState.color.dstFactor);
        DAWN_INVALID_IF(
            firstBlendState.alpha.operation != currBlendState.alpha.operation,
            "targets[%u].alpha.operation (%s) does not match targets[%u].alpha.operation (%s).",
            firstColorTargetIndex, firstBlendState.alpha.operation, targetIndex,
            currBlendState.alpha.operation);
        DAWN_INVALID_IF(
            firstBlendState.alpha.srcFactor != currBlendState.alpha.srcFactor,
            "targets[%u].alpha.srcFactor (%s) does not match targets[%u].alpha.srcFactor (%s).",
            firstColorTargetIndex, firstBlendState.alpha.srcFactor, targetIndex,
            currBlendState.alpha.srcFactor);
        DAWN_INVALID_IF(
            firstBlendState.alpha.dstFactor != currBlendState.alpha.dstFactor,
            "targets[%u].alpha.dstFactor (%s) does not match targets[%u].alpha.dstFactor (%s).",
            firstColorTargetIndex, firstBlendState.alpha.dstFactor, targetIndex,
            currBlendState.alpha.dstFactor);
    }
    return {};
}

ResultOrError<ShaderModuleEntryPoint> ValidateFragmentState(DeviceBase* device,
                                                            const FragmentState* descriptor,
                                                            const PipelineLayoutBase* layout,
                                                            const DepthStencilState* depthStencil,
                                                            const MultisampleState& multisample) {
    DAWN_INVALID_IF(descriptor->nextInChain != nullptr, "nextInChain must be nullptr.");

    ShaderModuleEntryPoint entryPoint;
    DAWN_TRY_ASSIGN_CONTEXT(
        entryPoint,
        ValidateProgrammableStage(device, descriptor->module, descriptor->entryPoint,
                                  descriptor->constants, layout, SingleShaderStage::Fragment),
        "validating fragment stage (%s, entryPoint: %s).", descriptor->module,
        descriptor->entryPoint);

    const EntryPointMetadata& fragmentMetadata = descriptor->module->GetEntryPoint(entryPoint.name);

    if (fragmentMetadata.usesFragDepth) {
        DAWN_INVALID_IF(depthStencil == nullptr,
                        "Depth stencil state is not present when fragment stage (%s, %s) is "
                        "writing to frag_depth.",
                        descriptor->module, entryPoint);
        const Format* depthStencilFormat;
        DAWN_TRY_ASSIGN(depthStencilFormat, device->GetInternalFormat(depthStencil->format));
        DAWN_INVALID_IF(!depthStencilFormat->HasDepth(),
                        "Depth stencil state format (%s) has no depth aspect when fragment stage "
                        "(%s, %s) is "
                        "writing to frag_depth.",
                        depthStencil->format, descriptor->module, entryPoint);
    }

    ColorAttachmentIndex maxColorAttachments{uint8_t(device->GetLimits().v1.maxColorAttachments)};
    DAWN_INVALID_IF(
        descriptor->targets.size() > maxColorAttachments,
        "Number of targets (%u) exceeds the maximum (%u).%s", descriptor->targets.size(),
        maxColorAttachments,
        DAWN_INCREASE_LIMIT_MESSAGE(device->GetAdapter()->GetLimits().v1, maxColorAttachments,
                                    uint8_t(descriptor->targets.size())));

    bool usesSrc1 = false;
    bool usesBlendSrc1 = false;
    ColorAttachmentFormats colorAttachmentFormats;
    ColorAttachmentMask targetMask;
    for (auto [i, target] : Enumerate(descriptor->targets)) {
        if (target.format == wgpu::TextureFormat::Undefined) {
            DAWN_INVALID_IF(target.blend,
                            "Color target[%u] blend state is set when the format is undefined.", i);
            continue;
        }
        targetMask.set(i);

        const Format* format;
        DAWN_TRY_ASSIGN(format, device->GetInternalFormat(target.format));

        DAWN_TRY_CONTEXT(
            ValidateColorTargetState(device, target, format, fragmentMetadata.fragmentOutputMask[i],
                                     fragmentMetadata.fragmentOutputVariables[i], multisample),
            "validating targets[%u] framebuffer output.", i);
        colorAttachmentFormats.push_back(&device->GetValidInternalFormat(target.format));

        if (fragmentMetadata.fragmentOutputVariables[i].blendSrc == 1u) {
            usesBlendSrc1 = true;
        }

        if (fragmentMetadata.fragmentInputMask[i]) {
            DAWN_TRY_CONTEXT(ValidateFramebufferInput(device, format,
                                                      fragmentMetadata.fragmentInputVariables[i]),
                             "validating targets[%u]'s framebuffer input.", i);
        }

        if (target.blend != nullptr) {
            usesSrc1 |= BlendStateUsesBlendFactorSrc1(*target.blend);
        }
    }

    if (usesSrc1) {
        DAWN_INVALID_IF(!usesBlendSrc1,
                        "One of the blend factor uses `blend_src(1)` while `blend_src(1)` is "
                        "missing from the fragment shader outputs.");
        DAWN_INVALID_IF(descriptor->targets.size() != ColorAttachmentIndex{uint8_t{1u}},
                        "One of the blend factor uses `blend_src(1)` but the color targets count "
                        "is not 1.");
    }

    auto extraFramebufferInputs = fragmentMetadata.fragmentInputMask & ~targetMask;
    DAWN_INVALID_IF(
        extraFramebufferInputs.any(),
        "Framebuffer input at index %u is used without a corresponding color target state.",
        GetHighestBitIndexPlusOne(extraFramebufferInputs).MinusOne());

    DAWN_TRY(ValidateColorAttachmentBytesPerSample(device, colorAttachmentFormats));

    if (multisample.alphaToCoverageEnabled) {
        DAWN_INVALID_IF(fragmentMetadata.usesSampleMaskOutput,
                        "alphaToCoverageEnabled is true when the sample_mask builtin is a "
                        "pipeline output of fragment stage of %s.",
                        descriptor->module);

        DAWN_INVALID_IF(descriptor->targets.empty(),
                        "alphaToCoverageEnabled is true when color target[0] is not present.");

        const ColorTargetState& firstTarget = *descriptor->targets.begin();
        DAWN_INVALID_IF(firstTarget.format == wgpu::TextureFormat::Undefined,
                        "alphaToCoverageEnabled is true when color target[0] is not present.");

        const Format* format;
        DAWN_TRY_ASSIGN(format, device->GetInternalFormat(firstTarget.format));
        DAWN_INVALID_IF(
            !format->HasAlphaChannel(),
            "alphaToCoverageEnabled is true when target[0].format (%s) has no alpha channel.",
            format->format);
    }

    if (device->IsCompatibilityMode()) {
        DAWN_INVALID_IF(
            fragmentMetadata.usesSampleMaskOutput,
            "sample_mask is not supported in compatibility mode in the fragment stage (%s, %s)",
            descriptor->module, entryPoint);

        DAWN_INVALID_IF(
            fragmentMetadata.usesSampleIndex,
            "sample_index is not supported in compatibility mode in the fragment stage (%s, %s)",
            descriptor->module, entryPoint);

        // Check that all the color target states match.
        ColorAttachmentIndex firstColorTargetIndex{};
        const ColorTargetState* firstColorTargetState = nullptr;
        for (auto i : targetMask) {
            if (!firstColorTargetState) {
                firstColorTargetState = &descriptor->targets[i];
                firstColorTargetIndex = i;
                continue;
            }

            DAWN_TRY_CONTEXT(
                ValidateColorTargetStatesMatch(firstColorTargetIndex, firstColorTargetState, i,
                                               &descriptor->targets[i]),
                "validating targets in compatibility mode.");
        }
    }

    return entryPoint;
}

MaybeError ValidateInterStageMatching(DeviceBase* device,
                                      const VertexState& vertexState,
                                      const ShaderModuleEntryPoint& vertexEntryPoint,
                                      const FragmentState& fragmentState,
                                      const ShaderModuleEntryPoint& fragmentEntryPoint) {
    const EntryPointMetadata& vertexMetadata =
        vertexState.module->GetEntryPoint(vertexEntryPoint.name);
    const EntryPointMetadata& fragmentMetadata =
        fragmentState.module->GetEntryPoint(fragmentEntryPoint.name);

    size_t maxInterStageShaderVariables = device->GetLimits().v1.maxInterStageShaderVariables;
    DAWN_CHECK(vertexMetadata.usedInterStageVariables.size() == maxInterStageShaderVariables);
    DAWN_CHECK(fragmentMetadata.usedInterStageVariables.size() == maxInterStageShaderVariables);
    for (size_t i = 0; i < maxInterStageShaderVariables; ++i) {
        if (!vertexMetadata.usedInterStageVariables[i]) {
            if (fragmentMetadata.usedInterStageVariables[i]) {
                return DAWN_VALIDATION_ERROR(
                    "The fragment input at location %u doesn't have a corresponding vertex output.",
                    i);
            }
            continue;
        }

        // It is valid that fragment output is a subset of vertex input
        if (!fragmentMetadata.usedInterStageVariables[i]) {
            continue;
        }
        const auto& vertexOutputInfo = vertexMetadata.interStageVariables[i];
        const auto& fragmentInputInfo = fragmentMetadata.interStageVariables[i];
        DAWN_INVALID_IF(
            vertexOutputInfo.baseType != fragmentInputInfo.baseType,
            "The base type (%s) of the vertex output at location %u is different from the "
            "base type (%s) of the fragment input at location %u.",
            vertexOutputInfo.baseType, i, fragmentInputInfo.baseType, i);

        DAWN_INVALID_IF(vertexOutputInfo.componentCount != fragmentInputInfo.componentCount,
                        "The component count (%u) of the vertex output at location %u is different "
                        "from the component count (%u) of the fragment input at location %u.",
                        vertexOutputInfo.componentCount, i, fragmentInputInfo.componentCount, i);

        DAWN_INVALID_IF(
            vertexOutputInfo.interpolationType != fragmentInputInfo.interpolationType,
            "The interpolation type (%s) of the vertex output at location %u is different "
            "from the interpolation type (%s) of the fragment input at location %u.",
            vertexOutputInfo.interpolationType, i, fragmentInputInfo.interpolationType, i);

        DAWN_INVALID_IF(
            vertexOutputInfo.interpolationSampling != fragmentInputInfo.interpolationSampling,
            "The interpolation sampling (%s) of the vertex output at location %u is "
            "different from the interpolation sampling (%s) of the fragment input at "
            "location %u.",
            vertexOutputInfo.interpolationSampling, i, fragmentInputInfo.interpolationSampling, i);

        if (device->IsCompatibilityMode()) {
            DAWN_INVALID_IF(
                vertexOutputInfo.interpolationType == InterpolationType::Linear,
                "The interpolation type (%s) of the vertex output at location %u is not "
                "supported in compatibility mode",
                vertexOutputInfo.interpolationType, i);

            DAWN_INVALID_IF(
                vertexOutputInfo.interpolationSampling == InterpolationSampling::Sample ||
                    vertexOutputInfo.interpolationSampling == InterpolationSampling::First,
                "The interpolation sampling (%s) of the vertex output at location %u is "
                "not supported in compatibility mode",
                vertexOutputInfo.interpolationSampling, i);

            DAWN_INVALID_IF(
                vertexOutputInfo.interpolationType == InterpolationType::Flat &&
                    vertexOutputInfo.interpolationSampling == InterpolationSampling::None,
                "The interpolation sampling (%s) of the vertex output at location %u when "
                "interpolation type is (%s)"
                "not supported in compatibility mode",
                vertexOutputInfo.interpolationSampling, i, vertexOutputInfo.interpolationType);
        }
    }

    return {};
}
}  // anonymous namespace

// Helper functions
size_t IndexFormatSize(wgpu::IndexFormat format) {
    switch (format) {
        case wgpu::IndexFormat::Uint16:
            return sizeof(uint16_t);
        case wgpu::IndexFormat::Uint32:
            return sizeof(uint32_t);
        case wgpu::IndexFormat::Undefined:
            break;
    }
    DAWN_UNREACHABLE();
}

bool IsStripPrimitiveTopology(wgpu::PrimitiveTopology primitiveTopology) {
    return primitiveTopology == wgpu::PrimitiveTopology::LineStrip ||
           primitiveTopology == wgpu::PrimitiveTopology::TriangleStrip;
}

MaybeError ValidateRenderPipelineDescriptor(DeviceBase* device,
                                            const RenderPipelineDescriptor* descriptor) {
    UnpackedPtr<RenderPipelineDescriptor> unpacked;
    DAWN_TRY_ASSIGN(unpacked, ValidateAndUnpack(descriptor));

    if (descriptor->layout != nullptr) {
        DAWN_TRY(device->ValidateObject(descriptor->layout));
    }

    ShaderModuleEntryPoint vertexEntryPoint;
    DAWN_TRY_ASSIGN_CONTEXT(vertexEntryPoint,
                            ValidateVertexState(device, &descriptor->vertex, descriptor->layout,
                                                descriptor->primitive.topology),
                            "validating vertex state.");

    DAWN_TRY_CONTEXT(ValidatePrimitiveState(device, &descriptor->primitive),
                     "validating primitive state.");

    if (descriptor->depthStencil) {
        DAWN_TRY_CONTEXT(ValidateDepthStencilState(device, descriptor->depthStencil,
                                                   descriptor->primitive.topology),
                         "validating depthStencil state.");
    }

    DAWN_TRY_CONTEXT(ValidateMultisampleState(device, &descriptor->multisample),
                     "validating multisample state.");

    DAWN_INVALID_IF(
        descriptor->multisample.alphaToCoverageEnabled && descriptor->fragment == nullptr,
        "alphaToCoverageEnabled is true when fragment state is not present.");

    if (descriptor->fragment != nullptr) {
        ShaderModuleEntryPoint fragmentEntryPoint;
        DAWN_TRY_ASSIGN_CONTEXT(
            fragmentEntryPoint,
            ValidateFragmentState(device, descriptor->fragment, descriptor->layout,
                                  descriptor->depthStencil, descriptor->multisample),
            "validating fragment state.");

        DAWN_TRY(ValidateInterStageMatching(device, descriptor->vertex, vertexEntryPoint,
                                            *(descriptor->fragment), fragmentEntryPoint));
    }

    bool hasStorageAttachments =
        descriptor->layout != nullptr && descriptor->layout->HasAnyStorageAttachments();
    bool hasColorAttachments =
        descriptor->fragment != nullptr && !descriptor->fragment->targets.empty();
    bool hasDepthStencilAttachment = descriptor->depthStencil != nullptr;
    DAWN_INVALID_IF(!hasColorAttachments && !hasDepthStencilAttachment && !hasStorageAttachments,
                    "No attachment was specified.");

    return {};
}

std::vector<StageAndDescriptor> GetRenderStagesAndSetPlaceholderShader(
    DeviceBase* device,
    const RenderPipelineDescriptor* descriptor) {
    std::vector<StageAndDescriptor> stages;
    stages.push_back({SingleShaderStage::Vertex, descriptor->vertex.module,
                      descriptor->vertex.entryPoint, descriptor->vertex.constants});
    if (descriptor->fragment != nullptr) {
        stages.push_back({SingleShaderStage::Fragment, descriptor->fragment->module,
                          descriptor->fragment->entryPoint, descriptor->fragment->constants});
    } else if (device->IsToggleEnabled(Toggle::UsePlaceholderFragmentInVertexOnlyPipeline)) {
        InternalPipelineStore* store = device->GetInternalPipelineStore();
        // The placeholder fragment shader module should already be initialized
        DAWN_CHECK(store->placeholderFragmentShader != nullptr);
        ShaderModuleBase* placeholderFragmentShader = store->placeholderFragmentShader.Get();
        stages.push_back(
            {SingleShaderStage::Fragment, placeholderFragmentShader, "fs_empty_main", {}});
    }
    return stages;
}

// RenderPipelineBase

RenderPipelineBase::RenderPipelineBase(DeviceBase* device,
                                       const UnpackedPtr<RenderPipelineDescriptor>& descriptor)
    : PipelineBase(device,
                   descriptor->layout,
                   descriptor->label,
                   GetRenderStagesAndSetPlaceholderShader(device, *descriptor)),
      mAttachmentState(device->GetOrCreateAttachmentState(descriptor, GetLayout())) {
    mVertexBufferCount = descriptor->vertex.buffers.size();

    for (auto [slot, buffer] : Enumerate(descriptor->vertex.buffers)) {
        // Skip unused slots
        if (buffer.stepMode == wgpu::VertexStepMode::Undefined && buffer.attributes.empty()) {
            continue;
        }

        mVertexBuffersUsed.set(slot);
        mVertexBufferInfos[slot].arrayStride = buffer.arrayStride;
        mVertexBufferInfos[slot].stepMode = (buffer.stepMode == wgpu::VertexStepMode::Undefined)
                                                ? wgpu::VertexStepMode::Vertex
                                                : buffer.stepMode;
        mVertexBufferInfos[slot].usedBytesInStride = 0;
        mVertexBufferInfos[slot].lastStride = 0;
        switch (mVertexBufferInfos[slot].stepMode) {
            case wgpu::VertexStepMode::Vertex:
                mVertexBuffersUsedAsVertexBuffer.set(slot);
                break;
            case wgpu::VertexStepMode::Instance:
                mVertexBuffersUsedAsInstanceBuffer.set(slot);
                break;
            case wgpu::VertexStepMode::Undefined:
                DAWN_UNREACHABLE();
        }

        for (auto [i, attribute] : Enumerate(buffer.attributes)) {
            VertexAttributeLocation location =
                VertexAttributeLocation(static_cast<uint8_t>(attribute.shaderLocation));

            mAttributeLocationsUsed.set(location);
            mAttributeInfos[location].shaderLocation = location;
            mAttributeInfos[location].vertexBufferSlot = slot;
            mAttributeInfos[location].offset = attribute.offset;
            mAttributeInfos[location].format = attribute.format;
            // Compute the access boundary of this attribute by adding attribute format size to
            // attribute offset. Although offset is in uint64_t, such sum must be no larger than
            // maxVertexBufferArrayStride (2048), which is promised by the GPUVertexBufferLayout
            // validation of creating render pipeline. Therefore, calculating in uint16_t will
            // cause no overflow.
            uint32_t formatByteSize = GetVertexFormatInfo(attribute.format).byteSize;
            DAWN_CHECK(attribute.offset <= 2048);
            uint16_t accessBoundary = uint16_t(attribute.offset) + uint16_t(formatByteSize);
            mVertexBufferInfos[slot].usedBytesInStride =
                std::max(mVertexBufferInfos[slot].usedBytesInStride, accessBoundary);
            mVertexBufferInfos[slot].lastStride =
                std::max(mVertexBufferInfos[slot].lastStride,
                         mAttributeInfos[location].offset + formatByteSize);
        }
    }

    mPrimitive = descriptor->primitive.WithTrivialFrontendDefaults();
    mMultisample = descriptor->multisample;

    if (mAttachmentState->HasDepthStencilAttachment()) {
        mDepthStencil = descriptor->depthStencil->WithTrivialFrontendDefaults();

        // Reify depth option for stencil-only formats
        const Format& format = device->GetValidInternalFormat(mDepthStencil.format);
        if (!format.HasDepth()) {
            mDepthStencil.depthWriteEnabled = wgpu::OptionalBool::False;
            mDepthStencil.depthCompare = wgpu::CompareFunction::Always;
        }
        if (format.HasDepth() && mDepthStencil.depthCompare == wgpu::CompareFunction::Undefined &&
            mDepthStencil.depthWriteEnabled != wgpu::OptionalBool::True &&
            mDepthStencil.stencilFront.depthFailOp == wgpu::StencilOperation::Keep &&
            mDepthStencil.stencilBack.depthFailOp == wgpu::StencilOperation::Keep) {
            mDepthStencil.depthCompare = wgpu::CompareFunction::Always;
        }
        mWritesDepth = mDepthStencil.depthWriteEnabled == wgpu::OptionalBool::True;
        if (mDepthStencil.stencilWriteMask) {
            if ((mPrimitive.cullMode != wgpu::CullMode::Front &&
                 (mDepthStencil.stencilFront.failOp != wgpu::StencilOperation::Keep ||
                  mDepthStencil.stencilFront.depthFailOp != wgpu::StencilOperation::Keep ||
                  mDepthStencil.stencilFront.passOp != wgpu::StencilOperation::Keep)) ||
                (mPrimitive.cullMode != wgpu::CullMode::Back &&
                 (mDepthStencil.stencilBack.failOp != wgpu::StencilOperation::Keep ||
                  mDepthStencil.stencilBack.depthFailOp != wgpu::StencilOperation::Keep ||
                  mDepthStencil.stencilBack.passOp != wgpu::StencilOperation::Keep))) {
                mWritesStencil = true;
            }
        }
    } 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.
        // - Most defaults come from the dawn::native::DepthStencilState definition.
        mDepthStencil = {};
        // - depthCompare is nullable for validation purposes but should default to Always.
        mDepthStencil.depthCompare = wgpu::CompareFunction::Always;
    }

    for (auto i : mAttachmentState->GetColorAttachmentsMask()) {
        // Vertex-only render pipeline have no color attachment. For a render pipeline with
        // color attachments, there must be a valid FragmentState.
        DAWN_CHECK(descriptor->fragment != nullptr);
        const ColorTargetState& target = descriptor->fragment->targets[i];
        mTargets[i] = target;

        if (target.blend != nullptr) {
            mTargetBlend[i] = target.blend->WithTrivialFrontendDefaults();
            mTargets[i].blend = &mTargetBlend[i];
        }
    }

    if (HasStage(SingleShaderStage::Fragment)) {
        mUsesFragDepth = GetStage(SingleShaderStage::Fragment).metadata->usesFragDepth;
        mUsesFragPosition = GetStage(SingleShaderStage::Fragment).metadata->usesFragPosition;
        mUsesSampleIndex = GetStage(SingleShaderStage::Fragment).metadata->usesSampleIndex;
        mUsesFramebufferFetch =
            GetStage(SingleShaderStage::Fragment).metadata->fragmentInputMask.any();
        mUseSampleRateShading =
            GetSampleCount() > 1 &&
            (GetStage(SingleShaderStage::Fragment).metadata->usesSampleInterpolants ||
             mUsesSampleIndex || mUsesFramebufferFetch);
    }

    if (HasStage(SingleShaderStage::Vertex)) {
        mUsesVertexIndex = GetStage(SingleShaderStage::Vertex).metadata->usesVertexIndex;
        mUsesInstanceIndex = GetStage(SingleShaderStage::Vertex).metadata->usesInstanceIndex;
    }

    SetContentHash(ComputeContentHash());
    GetObjectTrackingList()->Track(this);

    // Initialize the cache key to include the cache type and device information.
    StreamIn(&mCacheKey, CacheKey::Type::RenderPipeline, device->GetCacheKey());
}

MaybeError RenderPipelineBase::InitializeWithShaders() {
    return InitializeImpl();
}

RenderPipelineBase::RenderPipelineBase(DeviceBase* device,
                                       ObjectBase::ErrorTag tag,
                                       StringView label)
    : PipelineBase(device, tag, label) {}

RenderPipelineBase::~RenderPipelineBase() = default;

void RenderPipelineBase::DestroyImpl(DestroyReason reason) {
    Uncache();

    // Remove reference to the attachment state so that we don't have lingering references to
    // it preventing it from being uncached in the device.
    mAttachmentState = nullptr;
}

// static
Ref<RenderPipelineBase> RenderPipelineBase::MakeError(DeviceBase* device, StringView label) {
    class ErrorRenderPipeline final : public RenderPipelineBase {
      public:
        explicit ErrorRenderPipeline(DeviceBase* device, StringView label)
            : RenderPipelineBase(device, ObjectBase::kError, label) {}

        MaybeError InitializeImpl() override {
            DAWN_UNREACHABLE();
            return {};
        }
    };

    return AcquireRef(new ErrorRenderPipeline(device, label));
}

ObjectType RenderPipelineBase::GetType() const {
    return ObjectType::RenderPipeline;
}

const VertexAttributeMask& RenderPipelineBase::GetAttributeLocationsUsed() const {
    DAWN_CHECK(!IsError());
    return mAttributeLocationsUsed;
}

const VertexAttributeInfo& RenderPipelineBase::GetAttribute(
    VertexAttributeLocation location) const {
    DAWN_CHECK(!IsError());
    DAWN_CHECK(mAttributeLocationsUsed[location]);
    return mAttributeInfos[location];
}

const VertexBufferMask& RenderPipelineBase::GetVertexBuffersUsed() const {
    DAWN_CHECK(!IsError());
    return mVertexBuffersUsed;
}

const VertexBufferMask& RenderPipelineBase::GetVertexBuffersUsedAsVertexBuffer() const {
    DAWN_CHECK(!IsError());
    return mVertexBuffersUsedAsVertexBuffer;
}

const VertexBufferMask& RenderPipelineBase::GetVertexBuffersUsedAsInstanceBuffer() const {
    DAWN_CHECK(!IsError());
    return mVertexBuffersUsedAsInstanceBuffer;
}

const VertexBufferInfo& RenderPipelineBase::GetVertexBuffer(VertexBufferSlot slot) const {
    DAWN_CHECK(!IsError());
    DAWN_CHECK(mVertexBuffersUsed[slot]);
    return mVertexBufferInfos[slot];
}

VertexBufferSlot RenderPipelineBase::GetVertexBufferCount() const {
    DAWN_CHECK(!IsError());
    return mVertexBufferCount;
}

const ColorTargetState* RenderPipelineBase::GetColorTargetState(
    ColorAttachmentIndex attachmentSlot) const {
    DAWN_CHECK(!IsError());
    DAWN_CHECK(attachmentSlot < mTargets.size());
    return &mTargets[attachmentSlot];
}

const DepthStencilState* RenderPipelineBase::GetDepthStencilState() const {
    DAWN_CHECK(!IsError());
    return &mDepthStencil;
}

bool RenderPipelineBase::UsesStencil() const {
    return 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;
}

wgpu::PrimitiveTopology RenderPipelineBase::GetPrimitiveTopology() const {
    DAWN_CHECK(!IsError());
    return mPrimitive.topology;
}

wgpu::IndexFormat RenderPipelineBase::GetStripIndexFormat() const {
    DAWN_CHECK(!IsError());
    return mPrimitive.stripIndexFormat;
}

wgpu::CullMode RenderPipelineBase::GetCullMode() const {
    DAWN_CHECK(!IsError());
    return mPrimitive.cullMode;
}

wgpu::FrontFace RenderPipelineBase::GetFrontFace() const {
    DAWN_CHECK(!IsError());
    return mPrimitive.frontFace;
}

bool RenderPipelineBase::IsDepthBiasEnabled() const {
    DAWN_CHECK(!IsError());
    return mDepthStencil.depthBias != 0 || mDepthStencil.depthBiasSlopeScale != 0;
}

int32_t RenderPipelineBase::GetDepthBias() const {
    DAWN_CHECK(!IsError());
    return mDepthStencil.depthBias;
}

float RenderPipelineBase::GetDepthBiasSlopeScale() const {
    DAWN_CHECK(!IsError());
    return mDepthStencil.depthBiasSlopeScale;
}

float RenderPipelineBase::GetDepthBiasClamp() const {
    DAWN_CHECK(!IsError());
    return mDepthStencil.depthBiasClamp;
}

bool RenderPipelineBase::HasUnclippedDepth() const {
    DAWN_CHECK(!IsError());
    return mPrimitive.unclippedDepth;
}

ColorAttachmentMask RenderPipelineBase::GetColorAttachmentsMask() const {
    DAWN_CHECK(!IsError());
    return mAttachmentState->GetColorAttachmentsMask();
}

bool RenderPipelineBase::HasDepthStencilAttachment() const {
    DAWN_CHECK(!IsError());
    return mAttachmentState->HasDepthStencilAttachment();
}

wgpu::TextureFormat RenderPipelineBase::GetColorAttachmentFormat(
    ColorAttachmentIndex attachment) const {
    DAWN_CHECK(!IsError());
    return mTargets[attachment].format;
}

wgpu::TextureFormat RenderPipelineBase::GetDepthStencilFormat() const {
    DAWN_CHECK(!IsError());
    DAWN_CHECK(mAttachmentState->HasDepthStencilAttachment());
    return mDepthStencil.format;
}

uint32_t RenderPipelineBase::GetSampleCount() const {
    DAWN_CHECK(!IsError());
    return mAttachmentState->GetSampleCount();
}

uint32_t RenderPipelineBase::GetSampleMask() const {
    DAWN_CHECK(!IsError());
    return mMultisample.mask;
}

bool RenderPipelineBase::IsAlphaToCoverageEnabled() const {
    DAWN_CHECK(!IsError());
    return mMultisample.alphaToCoverageEnabled;
}

const AttachmentState* RenderPipelineBase::GetAttachmentState() const {
    DAWN_CHECK(!IsError());
    return mAttachmentState.Get();
}

bool RenderPipelineBase::WritesDepth() const {
    DAWN_CHECK(!IsError());
    return mWritesDepth;
}

bool RenderPipelineBase::WritesStencil() const {
    DAWN_CHECK(!IsError());
    return mWritesStencil;
}

bool RenderPipelineBase::UsesFragDepth() const {
    DAWN_CHECK(!IsError());
    return mUsesFragDepth;
}

bool RenderPipelineBase::UsesSampleIndex() const {
    DAWN_CHECK(!IsError());
    return mUsesSampleIndex;
}

bool RenderPipelineBase::UsesFragPosition() const {
    DAWN_CHECK(!IsError());
    return mUsesFragPosition;
}

bool RenderPipelineBase::UseSampleRateShading() const {
    DAWN_CHECK(!IsError());
    return mUseSampleRateShading;
}

bool RenderPipelineBase::UsesVertexIndex() const {
    DAWN_CHECK(!IsError());
    return mUsesVertexIndex;
}

bool RenderPipelineBase::UsesInstanceIndex() const {
    DAWN_CHECK(!IsError());
    return mUsesInstanceIndex;
}

bool RenderPipelineBase::UsesFramebufferFetch() const {
    DAWN_CHECK(!IsError());
    return mUsesFramebufferFetch;
}

size_t RenderPipelineBase::ComputeContentHash() {
    ObjectContentHasher recorder;

    // Record modules and layout
    recorder.Record(PipelineBase::ComputeContentHash());

    // Hierarchically record the attachment state.
    // It contains the attachments set, texture formats, and sample count.
    recorder.Record(mAttachmentState->GetContentHash());

    // Record attachments
    for (auto i : mAttachmentState->GetColorAttachmentsMask()) {
        const ColorTargetState& desc = *GetColorTargetState(i);
        recorder.Record(desc.writeMask);
        if (desc.blend != nullptr) {
            recorder.Record(desc.blend->color.operation, desc.blend->color.srcFactor,
                            desc.blend->color.dstFactor);
            recorder.Record(desc.blend->alpha.operation, desc.blend->alpha.srcFactor,
                            desc.blend->alpha.dstFactor);
        }
    }

    if (mAttachmentState->HasDepthStencilAttachment()) {
        const DepthStencilState& desc = mDepthStencil;
        recorder.Record(desc.depthWriteEnabled, desc.depthCompare);
        recorder.Record(desc.stencilReadMask, desc.stencilWriteMask);
        recorder.Record(desc.stencilFront.compare, desc.stencilFront.failOp,
                        desc.stencilFront.depthFailOp, desc.stencilFront.passOp);
        recorder.Record(desc.stencilBack.compare, desc.stencilBack.failOp,
                        desc.stencilBack.depthFailOp, desc.stencilBack.passOp);
        recorder.Record(desc.depthBias, desc.depthBiasSlopeScale, desc.depthBiasClamp);
    }

    // Record vertex state
    recorder.Record(mAttributeLocationsUsed);
    for (VertexAttributeLocation location : mAttributeLocationsUsed) {
        const VertexAttributeInfo& desc = GetAttribute(location);
        recorder.Record(desc.shaderLocation, desc.vertexBufferSlot, desc.offset, desc.format);
    }

    recorder.Record(mVertexBuffersUsed);
    for (VertexBufferSlot slot : mVertexBuffersUsed) {
        const VertexBufferInfo& desc = GetVertexBuffer(slot);
        recorder.Record(desc.arrayStride, desc.stepMode);
    }

    // Record primitive state
    recorder.Record(mPrimitive.topology, mPrimitive.stripIndexFormat, mPrimitive.frontFace,
                    mPrimitive.cullMode, mPrimitive.unclippedDepth);

    // Record multisample state
    // Sample count hashed as part of the attachment state
    recorder.Record(mMultisample.mask, mMultisample.alphaToCoverageEnabled);

    return recorder.GetContentHash();
}

bool RenderPipelineBase::EqualityFunc::operator()(const RenderPipelineBase* a,
                                                  const RenderPipelineBase* b) const {
    // Check the layout and shader stages.
    if (!PipelineBase::EqualForCache(a, b)) {
        return false;
    }

    // Check the attachment state.
    // It contains the attachments set, texture formats, and sample count.
    if (a->mAttachmentState.Get() != b->mAttachmentState.Get()) {
        return false;
    }

    if (a->mAttachmentState.Get() != nullptr) {
        for (auto i : a->mAttachmentState->GetColorAttachmentsMask()) {
            const ColorTargetState& descA = *a->GetColorTargetState(i);
            const ColorTargetState& descB = *b->GetColorTargetState(i);
            if (descA.writeMask != descB.writeMask) {
                return false;
            }
            if ((descA.blend == nullptr) != (descB.blend == nullptr)) {
                return false;
            }
            if (descA.blend != nullptr) {
                if (descA.blend->color.operation != descB.blend->color.operation ||
                    descA.blend->color.srcFactor != descB.blend->color.srcFactor ||
                    descA.blend->color.dstFactor != descB.blend->color.dstFactor) {
                    return false;
                }
                if (descA.blend->alpha.operation != descB.blend->alpha.operation ||
                    descA.blend->alpha.srcFactor != descB.blend->alpha.srcFactor ||
                    descA.blend->alpha.dstFactor != descB.blend->alpha.dstFactor) {
                    return false;
                }
            }
        }

        // Check depth/stencil state
        if (a->mAttachmentState->HasDepthStencilAttachment()) {
            const DepthStencilState& stateA = a->mDepthStencil;
            const DepthStencilState& stateB = b->mDepthStencil;

            DAWN_CHECK(!std::isnan(stateA.depthBiasSlopeScale));
            DAWN_CHECK(!std::isnan(stateB.depthBiasSlopeScale));
            DAWN_CHECK(!std::isnan(stateA.depthBiasClamp));
            DAWN_CHECK(!std::isnan(stateB.depthBiasClamp));

            if (stateA.depthWriteEnabled != stateB.depthWriteEnabled ||
                stateA.depthCompare != stateB.depthCompare ||
                stateA.depthBias != stateB.depthBias ||
                stateA.depthBiasSlopeScale != stateB.depthBiasSlopeScale ||
                stateA.depthBiasClamp != stateB.depthBiasClamp) {
                return false;
            }
            if (stateA.stencilFront.compare != stateB.stencilFront.compare ||
                stateA.stencilFront.failOp != stateB.stencilFront.failOp ||
                stateA.stencilFront.depthFailOp != stateB.stencilFront.depthFailOp ||
                stateA.stencilFront.passOp != stateB.stencilFront.passOp) {
                return false;
            }
            if (stateA.stencilBack.compare != stateB.stencilBack.compare ||
                stateA.stencilBack.failOp != stateB.stencilBack.failOp ||
                stateA.stencilBack.depthFailOp != stateB.stencilBack.depthFailOp ||
                stateA.stencilBack.passOp != stateB.stencilBack.passOp) {
                return false;
            }
            if (stateA.stencilReadMask != stateB.stencilReadMask ||
                stateA.stencilWriteMask != stateB.stencilWriteMask) {
                return false;
            }
        }
    }

    // Check vertex state
    if (a->mAttributeLocationsUsed != b->mAttributeLocationsUsed) {
        return false;
    }

    for (VertexAttributeLocation loc : a->mAttributeLocationsUsed) {
        const VertexAttributeInfo& descA = a->GetAttribute(loc);
        const VertexAttributeInfo& descB = b->GetAttribute(loc);
        if (descA.shaderLocation != descB.shaderLocation ||
            descA.vertexBufferSlot != descB.vertexBufferSlot || descA.offset != descB.offset ||
            descA.format != descB.format) {
            return false;
        }
    }

    if (a->mVertexBuffersUsed != b->mVertexBuffersUsed) {
        return false;
    }

    for (VertexBufferSlot slot : a->mVertexBuffersUsed) {
        const VertexBufferInfo& descA = a->GetVertexBuffer(slot);
        const VertexBufferInfo& descB = b->GetVertexBuffer(slot);
        if (descA.arrayStride != descB.arrayStride || descA.stepMode != descB.stepMode) {
            return false;
        }
    }

    // Check primitive state
    {
        const PrimitiveState& stateA = a->mPrimitive;
        const PrimitiveState& stateB = b->mPrimitive;
        if (stateA.topology != stateB.topology ||
            stateA.stripIndexFormat != stateB.stripIndexFormat ||
            stateA.frontFace != stateB.frontFace || stateA.cullMode != stateB.cullMode ||
            stateA.unclippedDepth != stateB.unclippedDepth) {
            return false;
        }
    }

    // Check multisample state
    {
        const MultisampleState& stateA = a->mMultisample;
        const MultisampleState& stateB = b->mMultisample;
        // Sample count already checked as part of the attachment state.
        if (stateA.mask != stateB.mask ||
            stateA.alphaToCoverageEnabled != stateB.alphaToCoverageEnabled) {
            return false;
        }
    }

    return true;
}

}  // namespace dawn::native
