// Copyright 2017 The Dawn Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "dawn/native/RenderPipeline.h"

#include <algorithm>
#include <cmath>
#include <sstream>

#include "dawn/common/BitSetIterator.h"
#include "dawn/native/ChainUtils_autogen.h"
#include "dawn/native/Commands.h"
#include "dawn/native/Device.h"
#include "dawn/native/InternalPipelineStore.h"
#include "dawn/native/ObjectContentHasher.h"
#include "dawn/native/ObjectType_autogen.h"
#include "dawn/native/ValidationUtils_autogen.h"
#include "dawn/native/VertexFormat.h"

namespace dawn::native {

// Helper functions
namespace {
MaybeError ValidateVertexAttribute(
    DeviceBase* device,
    const VertexAttribute* attribute,
    const EntryPointMetadata& metadata,
    uint64_t vertexBufferStride,
    ityp::bitset<VertexAttributeLocation, kMaxVertexAttributes>* attributesSetMask) {
    DAWN_TRY(ValidateVertexFormat(attribute->format));
    const VertexFormatInfo& formatInfo = GetVertexFormatInfo(attribute->format);

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

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

    // No underflow is possible because the max vertex format size is smaller than
    // kMaxVertexBufferArrayStride.
    ASSERT(kMaxVertexBufferArrayStride >= formatInfo.byteSize);
    DAWN_INVALID_IF(
        attribute->offset > kMaxVertexBufferArrayStride - formatInfo.byteSize,
        "Attribute offset (%u) with format %s (size: %u) doesn't fit in the maximum vertex "
        "buffer stride (%u).",
        attribute->offset, attribute->format, formatInfo.byteSize, kMaxVertexBufferArrayStride);

    // No overflow is possible because the offset is already validated to be less
    // than kMaxVertexBufferArrayStride.
    ASSERT(attribute->offset < kMaxVertexBufferArrayStride);
    DAWN_INVALID_IF(
        vertexBufferStride > 0 && attribute->offset + formatInfo.byteSize > vertexBufferStride,
        "Attribute offset (%u) with format %s (size: %u) doesn't fit in the vertex buffer "
        "stride (%u).",
        attribute->offset, attribute->format, formatInfo.byteSize, 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) does not match the "
                    "shader's base type (%s) in location (%u).",
                    formatInfo.baseType, 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,
    ityp::bitset<VertexAttributeLocation, kMaxVertexAttributes>* 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 (uint32_t i = 0; i < buffer->attributeCount; ++i) {
        DAWN_TRY_CONTEXT(ValidateVertexAttribute(device, &buffer->attributes[i], metadata,
                                                 buffer->arrayStride, attributesSetMask),
                         "validating attributes[%u].", i);
    }

    return {};
}

MaybeError ValidateVertexState(DeviceBase* device,
                               const VertexState* descriptor,
                               const PipelineLayoutBase* layout) {
    DAWN_INVALID_IF(descriptor->nextInChain != nullptr, "nextInChain must be nullptr.");

    DAWN_INVALID_IF(descriptor->bufferCount > kMaxVertexBuffers,
                    "Vertex buffer count (%u) exceeds the maximum number of vertex buffers (%u).",
                    descriptor->bufferCount, kMaxVertexBuffers);

    DAWN_TRY_CONTEXT(ValidateProgrammableStage(device, descriptor->module, descriptor->entryPoint,
                                               descriptor->constantCount, descriptor->constants,
                                               layout, SingleShaderStage::Vertex),
                     "validating vertex stage (module: %s, entryPoint: %s).", descriptor->module,
                     descriptor->entryPoint);
    const EntryPointMetadata& vertexMetadata =
        descriptor->module->GetEntryPoint(descriptor->entryPoint);

    ityp::bitset<VertexAttributeLocation, kMaxVertexAttributes> attributesSetMask;
    uint32_t totalAttributesNum = 0;
    for (uint32_t i = 0; i < descriptor->bufferCount; ++i) {
        DAWN_TRY_CONTEXT(ValidateVertexBufferLayout(device, &descriptor->buffers[i], vertexMetadata,
                                                    &attributesSetMask),
                         "validating buffers[%u].", i);
        totalAttributesNum += descriptor->buffers[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);

    // TODO(dawn:563): Specify which inputs were not used in error message.
    DAWN_INVALID_IF(!IsSubset(vertexMetadata.usedVertexInputs, attributesSetMask),
                    "Pipeline vertex stage uses vertex buffers not in the vertex state");

    return {};
}

MaybeError ValidatePrimitiveState(const DeviceBase* device, const PrimitiveState* descriptor) {
    DAWN_TRY(
        ValidateSingleSType(descriptor->nextInChain, wgpu::SType::PrimitiveDepthClampingState));
    const PrimitiveDepthClampingState* clampInfo = nullptr;
    FindInChain(descriptor->nextInChain, &clampInfo);
    if (clampInfo && !device->IsFeatureEnabled(Feature::DepthClamping)) {
        return DAWN_VALIDATION_ERROR("The depth clamping feature is not supported");
    }
    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 ValidateDepthStencilState(const DeviceBase* device,
                                     const DepthStencilState* 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));
    DAWN_INVALID_IF(!format->HasDepthOrStencil() || !format->isRenderable,
                    "Depth stencil format (%s) is not depth-stencil renderable.",
                    descriptor->format);

    DAWN_INVALID_IF(
        std::isnan(descriptor->depthBiasSlopeScale) || std::isnan(descriptor->depthBiasClamp),
        "Either depthBiasSlopeScale (%f) or depthBiasClamp (%f) is NaN.",
        descriptor->depthBiasSlopeScale, descriptor->depthBiasClamp);

    DAWN_INVALID_IF(
        !format->HasDepth() && (descriptor->depthCompare != wgpu::CompareFunction::Always ||
                                descriptor->depthWriteEnabled),
        "Depth stencil format (%s) doesn't have depth aspect while depthCompare (%s) is "
        "not %s or depthWriteEnabled (%u) is true.",
        descriptor->format, descriptor->depthCompare, wgpu::CompareFunction::Always,
        descriptor->depthWriteEnabled);

    DAWN_INVALID_IF(!format->HasStencil() && StencilTestEnabled(descriptor),
                    "Depth stencil format (%s) doesn't have stencil aspect while stencil "
                    "test or stencil write is enabled.",
                    descriptor->format);

    return {};
}

MaybeError ValidateMultisampleState(const MultisampleState* descriptor) {
    DAWN_INVALID_IF(descriptor->nextInChain != nullptr, "nextInChain must be nullptr.");

    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) {
    if (blendComponent.operation == wgpu::BlendOperation::Min ||
        blendComponent.operation == wgpu::BlendOperation::Max) {
        DAWN_INVALID_IF(blendComponent.srcFactor != wgpu::BlendFactor::One ||
                            blendComponent.dstFactor != wgpu::BlendFactor::One,
                        "Blend factor is not %s when blend operation is %s.",
                        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));
    DAWN_TRY(ValidateBlendComponent(descriptor->alpha));
    DAWN_TRY(ValidateBlendComponent(descriptor->color));

    return {};
}

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

MaybeError ValidateColorTargetState(
    DeviceBase* device,
    const ColorTargetState* descriptor,
    bool fragmentWritten,
    const EntryPointMetadata::FragmentOutputVariableInfo& fragmentOutputVariable) {
    DAWN_INVALID_IF(descriptor->nextInChain != nullptr, "nextInChain must be nullptr.");

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

    DAWN_TRY(ValidateColorWriteMask(descriptor->writeMask));

    const Format* format;
    DAWN_TRY_ASSIGN(format, device->GetInternalFormat(descriptor->format));
    DAWN_INVALID_IF(!format->IsColor() || !format->isRenderable,
                    "Color format (%s) is not color renderable.", descriptor->format);

    DAWN_INVALID_IF(
        descriptor->blend &&
            !(format->GetAspectInfo(Aspect::Color).supportedSampleTypes & SampleTypeBit::Float),
        "Blending is enabled but color format (%s) is not blendable.", descriptor->format);

    if (fragmentWritten) {
        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).",
            descriptor->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, descriptor->format,
                        format->componentCount);

        if (descriptor->blend) {
            if (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);
            }
        }
    } else {
        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 {};
}

MaybeError ValidateFragmentState(DeviceBase* device,
                                 const FragmentState* descriptor,
                                 const PipelineLayoutBase* layout) {
    DAWN_INVALID_IF(descriptor->nextInChain != nullptr, "nextInChain must be nullptr.");

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

    DAWN_INVALID_IF(descriptor->targetCount > kMaxColorAttachments,
                    "Number of targets (%u) exceeds the maximum (%u).", descriptor->targetCount,
                    kMaxColorAttachments);

    const EntryPointMetadata& fragmentMetadata =
        descriptor->module->GetEntryPoint(descriptor->entryPoint);
    for (ColorAttachmentIndex i(uint8_t(0));
         i < ColorAttachmentIndex(static_cast<uint8_t>(descriptor->targetCount)); ++i) {
        const ColorTargetState* target = &descriptor->targets[static_cast<uint8_t>(i)];
        if (target->format != wgpu::TextureFormat::Undefined) {
            DAWN_TRY_CONTEXT(
                ValidateColorTargetState(device, target, fragmentMetadata.fragmentOutputsWritten[i],
                                         fragmentMetadata.fragmentOutputVariables[i]),
                "validating targets[%u].", static_cast<uint8_t>(i));
        } else {
            DAWN_INVALID_IF(target->blend,
                            "Color target[%u] blend state is set when the format is undefined.",
                            static_cast<uint8_t>(i));
            DAWN_INVALID_IF(
                target->writeMask != wgpu::ColorWriteMask::None,
                "Color target[%u] write mask is set to (%s) when the format is undefined.",
                static_cast<uint8_t>(i), target->writeMask);
        }
    }

    return {};
}

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

    // TODO(dawn:563): Can this message give more details?
    DAWN_INVALID_IF(
        vertexMetadata.usedInterStageVariables != fragmentMetadata.usedInterStageVariables,
        "One or more fragment inputs and vertex outputs are not one-to-one matching");

    // TODO(dawn:802): Validate interpolation types and interpolition sampling types
    for (size_t i : IterateBitSet(vertexMetadata.usedInterStageVariables)) {
        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);
    }

    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;
    }
    UNREACHABLE();
}

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

MaybeError ValidateRenderPipelineDescriptor(DeviceBase* device,
                                            const RenderPipelineDescriptor* descriptor) {
    DAWN_INVALID_IF(descriptor->nextInChain != nullptr, "nextInChain must be nullptr.");

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

    DAWN_TRY_CONTEXT(ValidateVertexState(device, &descriptor->vertex, descriptor->layout),
                     "validating vertex state.");

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

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

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

    if (descriptor->fragment != nullptr) {
        DAWN_TRY_CONTEXT(ValidateFragmentState(device, descriptor->fragment, descriptor->layout),
                         "validating fragment state.");

        DAWN_INVALID_IF(descriptor->fragment->targetCount == 0 && !descriptor->depthStencil,
                        "Must have at least one color or depthStencil target.");

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

    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.constantCount,
                      descriptor->vertex.constants});
    if (descriptor->fragment != nullptr) {
        stages.push_back({SingleShaderStage::Fragment, descriptor->fragment->module,
                          descriptor->fragment->entryPoint, descriptor->fragment->constantCount,
                          descriptor->fragment->constants});
    } else if (device->IsToggleEnabled(Toggle::UsePlaceholderFragmentInVertexOnlyPipeline)) {
        InternalPipelineStore* store = device->GetInternalPipelineStore();
        // The placeholder fragment shader module should already be initialized
        DAWN_ASSERT(store->placeholderFragmentShader != nullptr);
        ShaderModuleBase* placeholderFragmentShader = store->placeholderFragmentShader.Get();
        stages.push_back(
            {SingleShaderStage::Fragment, placeholderFragmentShader, "fs_empty_main", 0, nullptr});
    }
    return stages;
}

bool StencilTestEnabled(const DepthStencilState* depthStencil) {
    return depthStencil->stencilBack.compare != wgpu::CompareFunction::Always ||
           depthStencil->stencilBack.failOp != wgpu::StencilOperation::Keep ||
           depthStencil->stencilBack.depthFailOp != wgpu::StencilOperation::Keep ||
           depthStencil->stencilBack.passOp != wgpu::StencilOperation::Keep ||
           depthStencil->stencilFront.compare != wgpu::CompareFunction::Always ||
           depthStencil->stencilFront.failOp != wgpu::StencilOperation::Keep ||
           depthStencil->stencilFront.depthFailOp != wgpu::StencilOperation::Keep ||
           depthStencil->stencilFront.passOp != wgpu::StencilOperation::Keep;
}

// RenderPipelineBase

RenderPipelineBase::RenderPipelineBase(DeviceBase* device,
                                       const RenderPipelineDescriptor* descriptor)
    : PipelineBase(device,
                   descriptor->layout,
                   descriptor->label,
                   GetRenderStagesAndSetPlaceholderShader(device, descriptor)),
      mAttachmentState(device->GetOrCreateAttachmentState(descriptor)) {
    mVertexBufferCount = descriptor->vertex.bufferCount;
    const VertexBufferLayout* buffers = descriptor->vertex.buffers;
    for (uint8_t slot = 0; slot < mVertexBufferCount; ++slot) {
        if (buffers[slot].attributeCount == 0) {
            continue;
        }

        VertexBufferSlot typedSlot(slot);

        mVertexBufferSlotsUsed.set(typedSlot);
        mVertexBufferInfos[typedSlot].arrayStride = buffers[slot].arrayStride;
        mVertexBufferInfos[typedSlot].stepMode = buffers[slot].stepMode;
        mVertexBufferInfos[typedSlot].usedBytesInStride = 0;
        mVertexBufferInfos[typedSlot].lastStride = 0;
        switch (buffers[slot].stepMode) {
            case wgpu::VertexStepMode::Vertex:
                mVertexBufferSlotsUsedAsVertexBuffer.set(typedSlot);
                break;
            case wgpu::VertexStepMode::Instance:
                mVertexBufferSlotsUsedAsInstanceBuffer.set(typedSlot);
                break;
            default:
                DAWN_UNREACHABLE();
        }

        for (uint32_t i = 0; i < buffers[slot].attributeCount; ++i) {
            VertexAttributeLocation location = VertexAttributeLocation(
                static_cast<uint8_t>(buffers[slot].attributes[i].shaderLocation));
            mAttributeLocationsUsed.set(location);
            mAttributeInfos[location].shaderLocation = location;
            mAttributeInfos[location].vertexBufferSlot = typedSlot;
            mAttributeInfos[location].offset = buffers[slot].attributes[i].offset;
            mAttributeInfos[location].format = buffers[slot].attributes[i].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(buffers[slot].attributes[i].format).byteSize;
            DAWN_ASSERT(buffers[slot].attributes[i].offset <= 2048);
            uint16_t accessBoundary =
                uint16_t(buffers[slot].attributes[i].offset) + uint16_t(formatByteSize);
            mVertexBufferInfos[typedSlot].usedBytesInStride =
                std::max(mVertexBufferInfos[typedSlot].usedBytesInStride, accessBoundary);
            mVertexBufferInfos[typedSlot].lastStride =
                std::max(mVertexBufferInfos[typedSlot].lastStride,
                         mAttributeInfos[location].offset + formatByteSize);
        }
    }

    mPrimitive = descriptor->primitive;
    const PrimitiveDepthClampingState* clampInfo = nullptr;
    FindInChain(mPrimitive.nextInChain, &clampInfo);
    if (clampInfo) {
        mClampDepth = clampInfo->clampDepth;
    }
    mMultisample = descriptor->multisample;

    if (mAttachmentState->HasDepthStencilAttachment()) {
        mDepthStencil = *descriptor->depthStencil;
        mWritesDepth = mDepthStencil.depthWriteEnabled;
        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.
        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;
        mDepthStencil.depthBias = 0;
        mDepthStencil.depthBiasSlopeScale = 0.0f;
        mDepthStencil.depthBiasClamp = 0.0f;
    }

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

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

    SetContentHash(ComputeContentHash());
    TrackInDevice();

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

RenderPipelineBase::RenderPipelineBase(DeviceBase* device) : PipelineBase(device) {
    TrackInDevice();
}

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

RenderPipelineBase::~RenderPipelineBase() = default;

void RenderPipelineBase::DestroyImpl() {
    if (IsCachedReference()) {
        // Do not uncache the actual cached object if we are a blueprint.
        GetDevice()->UncacheRenderPipeline(this);
    }

    // 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
RenderPipelineBase* RenderPipelineBase::MakeError(DeviceBase* device) {
    class ErrorRenderPipeline final : public RenderPipelineBase {
      public:
        explicit ErrorRenderPipeline(DeviceBase* device)
            : RenderPipelineBase(device, ObjectBase::kError) {}

        MaybeError Initialize() override {
            UNREACHABLE();
            return {};
        }
    };

    return new ErrorRenderPipeline(device);
}

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

const ityp::bitset<VertexAttributeLocation, kMaxVertexAttributes>&
RenderPipelineBase::GetAttributeLocationsUsed() const {
    ASSERT(!IsError());
    return mAttributeLocationsUsed;
}

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

const ityp::bitset<VertexBufferSlot, kMaxVertexBuffers>&
RenderPipelineBase::GetVertexBufferSlotsUsed() const {
    ASSERT(!IsError());
    return mVertexBufferSlotsUsed;
}

const ityp::bitset<VertexBufferSlot, kMaxVertexBuffers>&
RenderPipelineBase::GetVertexBufferSlotsUsedAsVertexBuffer() const {
    ASSERT(!IsError());
    return mVertexBufferSlotsUsedAsVertexBuffer;
}

const ityp::bitset<VertexBufferSlot, kMaxVertexBuffers>&
RenderPipelineBase::GetVertexBufferSlotsUsedAsInstanceBuffer() const {
    ASSERT(!IsError());
    return mVertexBufferSlotsUsedAsInstanceBuffer;
}

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

uint32_t RenderPipelineBase::GetVertexBufferCount() const {
    ASSERT(!IsError());
    return mVertexBufferCount;
}

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

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

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

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

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

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

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

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

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

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

bool RenderPipelineBase::ShouldClampDepth() const {
    ASSERT(!IsError());
    return mClampDepth;
}

ityp::bitset<ColorAttachmentIndex, kMaxColorAttachments>
RenderPipelineBase::GetColorAttachmentsMask() const {
    ASSERT(!IsError());
    return mAttachmentState->GetColorAttachmentsMask();
}

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

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

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

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

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

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

const AttachmentState* RenderPipelineBase::GetAttachmentState() const {
    ASSERT(!IsError());

    return mAttachmentState.Get();
}

bool RenderPipelineBase::WritesDepth() const {
    ASSERT(!IsError());

    return mWritesDepth;
}

bool RenderPipelineBase::WritesStencil() const {
    ASSERT(!IsError());

    return mWritesStencil;
}

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 (ColorAttachmentIndex i : IterateBitSet(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 : IterateBitSet(mAttributeLocationsUsed)) {
        const VertexAttributeInfo& desc = GetAttribute(location);
        recorder.Record(desc.shaderLocation, desc.vertexBufferSlot, desc.offset, desc.format);
    }

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

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

    // 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 (ColorAttachmentIndex i :
             IterateBitSet(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;

            ASSERT(!std::isnan(stateA.depthBiasSlopeScale));
            ASSERT(!std::isnan(stateB.depthBiasSlopeScale));
            ASSERT(!std::isnan(stateA.depthBiasClamp));
            ASSERT(!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 : IterateBitSet(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->mVertexBufferSlotsUsed != b->mVertexBufferSlotsUsed) {
        return false;
    }

    for (VertexBufferSlot slot : IterateBitSet(a->mVertexBufferSlotsUsed)) {
        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 ||
            a->mClampDepth != b->mClampDepth) {
            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
