// 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/PipelineLayout.h"

#include <algorithm>
#include <memory>
#include <utility>

#include "absl/container/inlined_vector.h"
#include "dawn/native/ObjectType_autogen.h"
#include "src/dawn/common/Enumerator.h"
#include "src/dawn/common/MatchVariant.h"
#include "src/dawn/common/Math.h"
#include "src/dawn/common/Range.h"
#include "src/dawn/native/BindGroupLayout.h"
#include "src/dawn/native/ChainUtils.h"
#include "src/dawn/native/CommandValidation.h"
#include "src/dawn/native/Device.h"
#include "src/dawn/native/Instance.h"
#include "src/dawn/native/ObjectContentHasher.h"
#include "src/dawn/native/ShaderModule.h"
#include "src/utils/assert.h"
#include "src/utils/compiler.h"
#include "src/utils/numeric.h"
#include "src/utils/span.h"

namespace dawn::native {

ResultOrValError<UnpackedPtr<PipelineLayoutDescriptor>> ValidatePipelineLayoutDescriptor(
    DeviceBase* device,
    const PipelineLayoutDescriptor* descriptor,
    PipelineCompatibilityToken pipelineCompatibilityToken) {
    UnpackedPtr<PipelineLayoutDescriptor> unpacked;
    DAWN_TRY_ASSIGN(unpacked, ValidateAndUnpack(descriptor));
    if (!device->IsToggleEnabled(Toggle::AllowExperimentalAPIs)) {
        // Only the chained structs that are part of the stable ABI may be used.
        DAWN_TRY_CONTEXT(unpacked.ValidateStable(),
                         "validating %s with allow_experimental_apis disabled", descriptor);
    }

    // A binding count that will be updated as we validate the various parts ot the pipeline layout.
    BindingCounts bindingCounts{};

    // Validation for any pixel local storage.
    if (auto* pls = unpacked.Get<PipelineLayoutPixelLocalStorage>()) {
        absl::InlinedVector<StorageAttachmentInfoForValidation, 4> attachments;
        for (auto [i, attachment] : Enumerate(pls->storageAttachments)) {
            const Format* format;
            DAWN_TRY_ASSIGN_CONTEXT(format, device->GetInternalFormat(attachment.format),
                                    "validating storageAttachments[%i]", i);
            DAWN_INVALID_IF(!format->SupportsStorageAttachment(),
                            "storageAttachments[%i]'s format (%s) cannot be used with %s.", i,
                            format->format, wgpu::TextureUsage::StorageAttachment);

            attachments.push_back({attachment.offset, attachment.format});
        }

        DAWN_TRY(ValidatePLSInfo(device, pls->totalPixelLocalStorageSize, attachments));
    }

    // Validation for the resource table, if any.
    bool usesResourceTable = false;
    if (auto* rt = unpacked.Get<PipelineLayoutResourceTable>()) {
        DAWN_INVALID_IF(rt->usesResourceTable &&
                            !device->HasFeature(Feature::ChromiumExperimentalSamplingResourceTable),
                        "Resource table used without the %s feature enabled.",
                        wgpu::FeatureName::ChromiumExperimentalSamplingResourceTable);
        usesResourceTable = rt->usesResourceTable;

        // Add to the limits the storage buffer that will be used for the availability data of the
        // resource table. Set a minimum binding size so as to not increment unverifiedBufferCount.
        BindGroupLayoutEntry availabilityEntry{
            .binding = 0,
            .visibility = kAllStages,
            .buffer =
                {
                    .type = wgpu::BufferBindingType::ReadOnlyStorage,
                    .minBindingSize = 4,
                },
        };
        IncrementBindingCounts(&bindingCounts, Unpack(&availabilityEntry));
    }

    // Validation for the bind group layouts.
    if (usesResourceTable) {
        DAWN_INVALID_IF(descriptor->bindGroupLayouts.untyped_size() >= kMaxBindGroups,
                        "bindGroupLayoutCount (%i) + 1 for the resource table is larger than the "
                        "maximum allowed (%i).",
                        descriptor->bindGroupLayouts.untyped_size(), kMaxBindGroups);
    } else {
        DAWN_INVALID_IF(descriptor->bindGroupLayouts.untyped_size() > kMaxBindGroups,
                        "bindGroupLayoutCount (%i) is larger than the maximum allowed (%i).",
                        descriptor->bindGroupLayouts.untyped_size(), kMaxBindGroups);
    }

    for (auto [i, bgl] : Enumerate(descriptor->bindGroupLayouts)) {
        if (bgl == nullptr) {
            continue;
        }

        DAWN_TRY(device->ValidateObject(descriptor->bindGroupLayouts[i]));
        DAWN_INVALID_IF(bgl->GetPipelineCompatibilityToken() != pipelineCompatibilityToken,
                        "bindGroupLayouts[%i] (%s) is used to create a pipeline layout but it was "
                        "created as part of a pipeline's default layout.",
                        i, bgl);

        AccumulateBindingCounts(&bindingCounts,
                                bgl->GetInternalBindGroupLayout()->GetValidationBindingCounts());
    }

    // Validate immediateSize.
    if (descriptor->immediateSize) {
        DAWN_INVALID_IF(!IsAligned(descriptor->immediateSize, kImmediateElementByteSize),
                        "immediateSize (%i) is not a multiple of %i bytes.",
                        descriptor->immediateSize, kImmediateElementByteSize);
        uint32_t maxImmediateSize = device->GetLimits().v1.maxImmediateSize;
        DAWN_INVALID_IF(descriptor->immediateSize > maxImmediateSize,
                        "immediateSize (%i) is larger than the maximum allowed (%i).",
                        descriptor->immediateSize, maxImmediateSize);
    }

    DAWN_TRY(ValidateBindingCounts(device->GetLimits(), bindingCounts, device->GetAdapter()));
    return unpacked;
}

StageAndDescriptor::StageAndDescriptor(SingleShaderStage shaderStage,
                                       ShaderModuleBase* module,
                                       StringView entryPoint,
                                       Span<const ConstantEntry> constants)
    : shaderStage(shaderStage),
      module(module),
      entryPoint(module->ReifyEntryPointName(entryPoint, shaderStage).name),
      constants(constants) {}

// PipelineLayoutBase

PipelineLayoutBase::PipelineLayoutBase(DeviceBase* device,
                                       const UnpackedPtr<PipelineLayoutDescriptor>& descriptor,
                                       ApiObjectBase::UntrackedByDeviceTag tag)
    : ApiObjectBase(device, descriptor->label),
      mImmediateDataRangeByteSize(descriptor->immediateSize) {
    DAWN_CHECK(descriptor->bindGroupLayouts.size() <= kMaxBindGroupsTyped);

    // According to WebGPU SPEC of CreatePipelineLayout(), if bindGroupLayouts[i] is null or
    // bindGroupLayouts[i].[[descriptor]].entries is empty, treat bindGroupLayouts[i] as an
    // empty bind group layout. So here unspecified or null bind group layouts can be set to
    // `device->GetEmptyBindGroupLayout()`.
    mBindGroupLayouts.fill(device->GetEmptyBindGroupLayout());

    for (auto [group, bgl] : Enumerate(descriptor->bindGroupLayouts)) {
        // Keep the default empty bind group layouts for nullptr bind group layouts
        if (bgl == nullptr) {
            continue;
        }

        // Set the bind group layout even if it is empty to copy over the empty bind group layouts
        // that have a pipeline compatibility token.
        mBindGroupLayouts[group] = bgl;
        mMask.set(group, !bgl->IsEmpty());
    }

    // Gather the PLS information.
    if (auto* pls = descriptor.Get<PipelineLayoutPixelLocalStorage>()) {
        mHasPLS = true;
        mStorageAttachmentSlots = std::vector<wgpu::TextureFormat>(
            checked_cast<size_t>(pls->totalPixelLocalStorageSize / kPLSSlotByteSize),
            wgpu::TextureFormat::Undefined);
        for (const PipelineLayoutStorageAttachment& attachment : pls->storageAttachments) {
            size_t slot = checked_cast<size_t>(attachment.offset / kPLSSlotByteSize);
            mStorageAttachmentSlots[slot] = attachment.format;
        }
    }
    // Gather the resource table information.
    if (auto* rt = descriptor.Get<PipelineLayoutResourceTable>()) {
        mUsesResourceTable = rt->usesResourceTable;
    }
}

PipelineLayoutBase::PipelineLayoutBase(DeviceBase* device,
                                       const UnpackedPtr<PipelineLayoutDescriptor>& descriptor)
    : PipelineLayoutBase(device, descriptor, kUntrackedByDevice) {
    GetObjectTrackingList()->Track(this);
}

PipelineLayoutBase::PipelineLayoutBase(DeviceBase* device,
                                       ObjectBase::ErrorTag tag,
                                       StringView label)
    : ApiObjectBase(device, tag, label) {}

PipelineLayoutBase::~PipelineLayoutBase() = default;

void PipelineLayoutBase::DestroyImpl(DestroyReason reason) {
    Uncache();
}

// static
Ref<PipelineLayoutBase> PipelineLayoutBase::MakeError(DeviceBase* device, StringView label) {
    return AcquireRef(new PipelineLayoutBase(device, ObjectBase::kError, label));
}

namespace {

// Helper function used to merge multiple TextureSampleTypes for the same binding together.
ResultOrValError<wgpu::TextureSampleType> MostSpecificSampleTypeIfCompatible(
    wgpu::TextureSampleType a,
    wgpu::TextureSampleType b) {
    if (a == b) {
        return a;
    }

    // If a binding is UnknownFilterableFloat then the other one is more specific (the case where it
    // is also UnknownFilterableFloat is handled above and it keeps the same value as it is "as
    // specific").
    if (a == kUnknownFilterableFloatSampleType &&
        (b == wgpu::TextureSampleType::UnfilterableFloat || b == wgpu::TextureSampleType::Float)) {
        return b;
    }
    if (b == kUnknownFilterableFloatSampleType &&
        (a == wgpu::TextureSampleType::UnfilterableFloat || a == wgpu::TextureSampleType::Float)) {
        return a;
    }

    return DAWN_VALIDATION_ERROR("Texture sample types are not compatible (%s vs %s).", a, b);
}

// Helper function used to merge multiple SamplerBindingType for the same binding together.
ResultOrValError<wgpu::SamplerBindingType> MostSpecificSamplerTypeIfCompatible(
    wgpu::SamplerBindingType a,
    wgpu::SamplerBindingType b) {
    if (a == b) {
        return a;
    }

    // If a binding is UnknownFiltering then the other one is more specific (the case where it is
    // also UnknownFiltering is handled above and it keeps the same value as it is "as specific").
    if (a == kUnknownFilteringSamplerBindingType &&
        (b == wgpu::SamplerBindingType::Filtering || b == wgpu::SamplerBindingType::NonFiltering)) {
        return b;
    }
    if (b == kUnknownFilteringSamplerBindingType &&
        (a == wgpu::SamplerBindingType::Filtering || a == wgpu::SamplerBindingType::NonFiltering)) {
        return b;
    }

    return DAWN_VALIDATION_ERROR("Sampler binding types are not compatible (%s vs %s).", a, b);
}

// Merges two entries at the same location, if they are allowed to be merged.
MaybeValError MergeEntries(BindGroupLayoutEntry* modifiedEntry,
                           const BindGroupLayoutEntry& mergedEntry) {
    DAWN_CHECK(modifiedEntry->binding == mergedEntry.binding);

    BindingInfoType modifiedType = GetBindingInfoType(modifiedEntry);
    BindingInfoType mergedType = GetBindingInfoType(&mergedEntry);
    DAWN_INVALID_IF(modifiedType != mergedType, "Binding types differ (%s vs %s).", modifiedType,
                    mergedType);

    // Use the OR of all the stages at which we find this binding.
    modifiedEntry->visibility |= mergedEntry.visibility;

    // Size binding_arrays to be the maximum of the required array sizes.
    modifiedEntry->bindingArraySize =
        std::max(modifiedEntry->bindingArraySize, mergedEntry.bindingArraySize);

    switch (mergedType) {
        case BindingInfoType::Buffer:
            DAWN_INVALID_IF(modifiedEntry->buffer.type != mergedEntry.buffer.type,
                            "Buffer binding types differs (%s vs. %s).", modifiedEntry->buffer.type,
                            mergedEntry.buffer.type);
            DAWN_INVALID_IF(
                modifiedEntry->buffer.hasDynamicOffset != mergedEntry.buffer.hasDynamicOffset,
                "Buffer dynamic offsets differs (%v vs. %v).",
                modifiedEntry->buffer.hasDynamicOffset, mergedEntry.buffer.hasDynamicOffset);

            // Use the max |minBufferBindingSize| we find.
            modifiedEntry->buffer.minBindingSize =
                std::max(modifiedEntry->buffer.minBindingSize, mergedEntry.buffer.minBindingSize);
            break;

        case BindingInfoType::Texture: {
            DAWN_INVALID_IF(
                modifiedEntry->texture.viewDimension != mergedEntry.texture.viewDimension,
                "Texture dimensions differs (%s vs. %s).", modifiedEntry->texture.viewDimension,
                mergedEntry.texture.viewDimension);
            DAWN_INVALID_IF(modifiedEntry->texture.multisampled != mergedEntry.texture.multisampled,
                            "Texture multisampled differs (%v vs. %v).",
                            modifiedEntry->texture.multisampled, mergedEntry.texture.multisampled);

            DAWN_TRY_ASSIGN(modifiedEntry->texture.sampleType,
                            MostSpecificSampleTypeIfCompatible(modifiedEntry->texture.sampleType,
                                                               mergedEntry.texture.sampleType));
            break;
        }

        case BindingInfoType::StorageTexture:
            DAWN_INVALID_IF(
                modifiedEntry->storageTexture.access != mergedEntry.storageTexture.access,
                "Storage texture accesses differs (%s vs. %s).",
                modifiedEntry->storageTexture.access, mergedEntry.storageTexture.access);
            DAWN_INVALID_IF(
                modifiedEntry->storageTexture.format != mergedEntry.storageTexture.format,
                "Storage texture formats differs (%s vs. %s).",
                modifiedEntry->storageTexture.format, mergedEntry.storageTexture.format);
            DAWN_INVALID_IF(modifiedEntry->storageTexture.viewDimension !=
                                mergedEntry.storageTexture.viewDimension,
                            "Storage texture dimensions differs (%s vs. %s).",
                            modifiedEntry->storageTexture.viewDimension,
                            mergedEntry.storageTexture.viewDimension);
            break;

        case BindingInfoType::Sampler:
            DAWN_TRY_ASSIGN(modifiedEntry->sampler.type,
                            MostSpecificSamplerTypeIfCompatible(modifiedEntry->sampler.type,
                                                                mergedEntry.sampler.type));
            break;

        case BindingInfoType::ExternalTexture:
            // Nothing to check or merge.
            break;

        // Types that cannot be defaulted (yet?)
        case BindingInfoType::StaticSampler:
        case BindingInfoType::TexelBuffer:
        case BindingInfoType::InputAttachment:
            DAWN_UNREACHABLE();
    }

    return {};
}

BindGroupLayoutEntry ConvertMetadataToEntry(
    std::vector<std::unique_ptr<wgpu::TexelBufferBindingLayout>>& texelBufferLayouts,
    const ShaderBindingInfo& shaderBinding,
    const ExternalTextureBindingLayout* externalTextureBindingEntry) {
    BindGroupLayoutEntry entry = {};
    entry.bindingArraySize = uint32_t{shaderBinding.arraySize};

    MatchVariant(
        shaderBinding.bindingInfo,
        [&](const BufferBindingInfo& bindingInfo) {
            entry.buffer.type = bindingInfo.type;
            entry.buffer.minBindingSize = bindingInfo.minBindingSize;
        },
        [&](const SamplerBindingInfo& bindingInfo) { entry.sampler.type = bindingInfo.type; },
        [&](const TextureBindingInfo& bindingInfo) {
            entry.texture.sampleType = bindingInfo.sampleType;
            entry.texture.viewDimension = bindingInfo.viewDimension;
            entry.texture.multisampled = bindingInfo.multisampled;
        },
        [&](const StorageTextureBindingInfo& bindingInfo) {
            entry.storageTexture.access = bindingInfo.access;
            entry.storageTexture.format = bindingInfo.format;
            entry.storageTexture.viewDimension = bindingInfo.viewDimension;
        },
        [&](const TexelBufferBindingInfo& bindingInfo) {
            auto layout = std::make_unique<wgpu::TexelBufferBindingLayout>();
            layout->format = bindingInfo.format;
            layout->access = bindingInfo.access;
            texelBufferLayouts.push_back(std::move(layout));
            entry.nextInChain = texelBufferLayouts.back().get();
        },
        [&](const ExternalTextureBindingInfo&) { entry.nextInChain = externalTextureBindingEntry; },
        [&](const InputAttachmentBindingInfo& bindingInfo) {
            entry.texture.sampleType = bindingInfo.sampleType;
            entry.texture.viewDimension = kInternalInputAttachmentDim;
        });

    return entry;
}

// Creates the BGL from the entries for a stage, checking it is valid.
ResultOrUnknownError<Ref<BindGroupLayoutBase>> CreateBGL(
    DeviceBase* device,
    absl::flat_hash_map<BindingNumber, BindGroupLayoutEntry> entries,
    PipelineCompatibilityToken pipelineCompatibilityToken,
    bool allowInternalBinding) {
    // Put all the values from the map in a vector
    std::vector<BindGroupLayoutEntry> entryVec;
    entryVec.reserve(entries.size());
    for (auto& [_, entry] : entries) {
        entryVec.push_back(entry);
    }

    // Create and validate the BGL
    BindGroupLayoutDescriptor desc = {};
    desc.entries = entryVec;

    UnpackedPtr<BindGroupLayoutDescriptor> unpacked;
    if (device->IsValidationEnabled()) {
        DAWN_TRY_ASSIGN_CONTEXT(
            unpacked, ValidateBindGroupLayoutDescriptor(device, &desc, allowInternalBinding),
            "validating %s", &desc);
    } else {
        unpacked = Unpack(&desc);
    }
    return device->GetOrCreateBindGroupLayout(unpacked, pipelineCompatibilityToken);
}

// Resolves all the samplers with type kUnknownFilteringSamplerBindingType and all textures with
// sample type kUnknownFilterableFloatSampleType to concrete values.
void ResolveUnknownTypes(
    const std::vector<StageAndDescriptor>& stages,
    PerBindGroup<absl::flat_hash_map<BindingNumber, BindGroupLayoutEntry>>* entryData) {
    // Handle the constraint where an unknown sampler used with a non-filterable texture
    // (unfilterable-float, sint or uint) must be non-filtering. Note that unknown textures used
    // with samplers can only be changed to filterable floats in the rest of the resolving, so no
    // new constraints on samplers will be created after this.
    for (const StageAndDescriptor& stage : stages) {
        for (const auto& pair :
             stage.module->GetEntryPoint(stage.entryPoint).samplerAndNonSamplerTexturePairs) {
            if (pair.sampler == EntryPointMetadata::nonSamplerBindingPoint) {
                continue;
            }

            BindGroupLayoutEntry* s = &entryData->at(pair.sampler.group)[pair.sampler.binding];
            BindGroupLayoutEntry* t = &entryData->at(pair.texture.group)[pair.texture.binding];
            if (s->sampler.type != kUnknownFilteringSamplerBindingType) {
                continue;
            }

            // Pairs can reference external textures, they are always filterable.
            if (t->texture.sampleType == wgpu::TextureSampleType::BindingNotUsed) {
                DAWN_CHECK(t->nextInChain != nullptr &&
                           t->nextInChain->sType == wgpu::SType::ExternalTextureBindingLayout);
                continue;
            }

            if (t->texture.sampleType != wgpu::TextureSampleType::Float &&
                t->texture.sampleType != kUnknownFilterableFloatSampleType) {
                s->sampler.type = wgpu::SamplerBindingType::NonFiltering;
            }
        }
    }
    // All the other unknown samplers have no specific constraints and are made filtering as that's
    // the least constraining for samplers that can be put in BindGroups.
    for (const StageAndDescriptor& stage : stages) {
        const EntryPointMetadata& metadata = stage.module->GetEntryPoint(stage.entryPoint);

        for (auto [group, groupBindings] : Enumerate(metadata.bindings)) {
            for (const auto& [bindingNumber, shaderBinding] : groupBindings) {
                BindGroupLayoutEntry* entry = &entryData->at(group)[bindingNumber];
                if (entry->sampler.type == kUnknownFilteringSamplerBindingType) {
                    entry->sampler.type = wgpu::SamplerBindingType::Filtering;
                }
            }
        }
    }

    // Handle the constraint where an unknown texture used with a filtering sampler must be a
    // filterable float.
    for (const StageAndDescriptor& stage : stages) {
        for (const auto& pair :
             stage.module->GetEntryPoint(stage.entryPoint).samplerAndNonSamplerTexturePairs) {
            if (pair.sampler == EntryPointMetadata::nonSamplerBindingPoint) {
                continue;
            }

            BindGroupLayoutEntry* s = &entryData->at(pair.sampler.group)[pair.sampler.binding];
            BindGroupLayoutEntry* t = &entryData->at(pair.texture.group)[pair.texture.binding];

            // Pairs can reference external textures, skip handling them.
            if (t->texture.sampleType == wgpu::TextureSampleType::BindingNotUsed) {
                DAWN_CHECK(t->nextInChain != nullptr &&
                           t->nextInChain->sType == wgpu::SType::ExternalTextureBindingLayout);
                continue;
            }

            DAWN_CHECK(s->sampler.type != kUnknownFilteringSamplerBindingType);
            if (t->texture.sampleType == kUnknownFilterableFloatSampleType &&
                s->sampler.type == wgpu::SamplerBindingType::Filtering) {
                t->texture.sampleType = wgpu::TextureSampleType::Float;
            }
        }
    }

    // All the other unknown textures have no specific constraints and are made unfilterable as
    // that's the least constraining for textures that can be put in BindGroups.
    for (const StageAndDescriptor& stage : stages) {
        const EntryPointMetadata& metadata = stage.module->GetEntryPoint(stage.entryPoint);

        for (auto [group, groupBindings] : Enumerate(metadata.bindings)) {
            for (const auto& [bindingNumber, shaderBinding] : groupBindings) {
                BindGroupLayoutEntry* entry = &entryData->at(group)[bindingNumber];
                if (entry->texture.sampleType == kUnknownFilterableFloatSampleType) {
                    entry->texture.sampleType = wgpu::TextureSampleType::UnfilterableFloat;
                }
            }
        }
    }
}

}  // namespace

// static
ResultOrUnknownError<Ref<PipelineLayoutBase>> PipelineLayoutBase::CreateDefault(
    DeviceBase* device,
    std::vector<StageAndDescriptor> stages,
    bool allowInternalBinding) {
    DAWN_CHECK(!stages.empty());

    // Does the trivial conversions from a ShaderBindingInfo to a BindGroupLayoutEntry
    std::vector<std::unique_ptr<wgpu::TexelBufferBindingLayout>> texelBufferLayouts;

    PipelineCompatibilityToken pipelineCompatibilityToken =
        device->GetNextPipelineCompatibilityToken();

    // Data which BindGroupLayoutDescriptor will point to for creation
    PerBindGroup<absl::flat_hash_map<BindingNumber, BindGroupLayoutEntry>> entryData = {};

    // External texture binding layouts are chained structs that are set as a pointer within
    // the bind group layout entry. We declare an entry here so that it can be used when needed
    // in each BindGroupLayoutEntry and so it can stay alive until the call to
    // GetOrCreateBindGroupLayout. Because ExternalTextureBindingLayout is an empty struct,
    // there's no issue with using the same struct multiple times.
    ExternalTextureBindingLayout externalTextureBindingLayout;

    bool usesResourceTable = false;
    uint32_t immediateDataRangeByteSize = 0;

    // Loops over all the reflected BindGroupLayoutEntries from shaders.
    for (const StageAndDescriptor& stage : stages) {
        const EntryPointMetadata& metadata = stage.module->GetEntryPoint(stage.entryPoint);

        // Check if at least one stage uses a resource table
        if (metadata.usesResourceTable) {
            usesResourceTable = true;
        }

        // TODO(dawn:1704): Find if we can usefully deduce the PLS for the pipeline layout.
        DAWN_INVALID_IF(
            metadata.usesPixelLocal,
            "Implicit layouts are not supported for entry-points using `pixel_local` blocks.");

        for (auto [group, groupBindings] : Enumerate(metadata.bindings)) {
            for (const auto& [bindingNumber, shaderBinding] : groupBindings) {
                // Create the BindGroupLayoutEntry
                BindGroupLayoutEntry entry = ConvertMetadataToEntry(
                    texelBufferLayouts, shaderBinding, &externalTextureBindingLayout);
                entry.binding = uint32_t{bindingNumber};
                entry.visibility = StageBit(stage.shaderStage);

                // Add it to our map of all entries, if there is an existing entry, then we
                // need to merge, if we can.
                const auto& [existingEntry, inserted] =
                    entryData[group].insert({bindingNumber, entry});
                if (!inserted) {
                    DAWN_TRY_CONTEXT(MergeEntries(&existingEntry->second, entry),
                                     "merging implicit bindings for @group(%u) @binding(%u).",
                                     group, bindingNumber);
                }
            }
        }

        // For render pipeline that might has vertex and fragment stages, it is possible that each
        // stage has their own immediate data variable shares the same immediate data block. Pick
        // the max size of immediate data variable from vertex and fragment stage as the
        // pipelineLayout immediate data block size.
        immediateDataRangeByteSize =
            std::max(immediateDataRangeByteSize, metadata.immediateDataRangeByteSize);
    }

    // Some sampler and texture bindings are created with an unknown sampler type / texture sample
    // type and must be resolved to concrete types based on which texture/sampler pairs are
    // statically used.
    ResolveUnknownTypes(stages, &entryData);

    // Create the bind group layouts, including the empty ones as all the bind group layouts should
    // be created with `pipelineCompatibilityToken` whether they are empty or not.
    PerBindGroup<Ref<BindGroupLayoutBase>> bindGroupLayouts = {};
    for (auto group : Range(kMaxBindGroupsTyped)) {
        DAWN_TRY_ASSIGN(bindGroupLayouts[group],
                        CreateBGL(device, std::move(entryData[group]), pipelineCompatibilityToken,
                                  allowInternalBinding));
    }

    // Create the deduced pipeline layout, validating if it is valid.
    PerBindGroup<BindGroupLayoutBase*> bgls = {};
    for (auto group : Range(kMaxBindGroupsTyped)) {
        bgls[group] = bindGroupLayouts[group].Get();
    }

    PipelineLayoutDescriptor desc = {};
    desc.bindGroupLayouts = bgls;
    desc.immediateSize = immediateDataRangeByteSize;

    PipelineLayoutResourceTable resourceTable;
    if (usesResourceTable) {
        resourceTable.usesResourceTable = true;
        resourceTable.nextInChain = desc.nextInChain;
        desc.nextInChain = &resourceTable;

        // The resource table uses one BGL entry, so remove the last one, only if it's empty, to
        // make room for it. If it's not empty, this means kMaxBindGroups were referenced in the
        // shader, which will trigger a validation error in CreatePipelineLayout that too many BGLs
        // are used with the resource table.
        desc.bindGroupLayouts =
            desc.bindGroupLayouts.first(desc.bindGroupLayouts.size().MinusOne());
    }

    Ref<PipelineLayoutBase> result;
    DAWN_TRY_ASSIGN(result, device->CreatePipelineLayout(&desc, pipelineCompatibilityToken));
    DAWN_CHECK(!result->IsError());

    // Validate that the auto pipeline layout is compatible with the current pipeline.
    // Note: the currently specified rules can generate invalid default layouts.
    // Hopefully the spec will be updated to prevent this.
    // See: https://github.com/gpuweb/gpuweb/issues/4952
    for (const StageAndDescriptor& stage : stages) {
        const EntryPointMetadata& metadata = stage.module->GetEntryPoint(stage.entryPoint);
        DAWN_TRY(ValidateCompatibilityWithPipelineLayout(device, metadata, result.Get()));
    }

    return std::move(result);
}

ObjectType PipelineLayoutBase::GetType() const {
    return ObjectType::PipelineLayout;
}

const BindGroupLayoutBase* PipelineLayoutBase::GetFrontendBindGroupLayout(
    BindGroupIndex group) const {
    DAWN_CHECK(!IsError());
    const BindGroupLayoutBase* bgl = mBindGroupLayouts[group].Get();
    DAWN_CHECK(bgl != nullptr);
    return bgl;
}

BindGroupLayoutBase* PipelineLayoutBase::GetFrontendBindGroupLayout(BindGroupIndex group) {
    DAWN_CHECK(!IsError());
    BindGroupLayoutBase* bgl = mBindGroupLayouts[group].Get();
    DAWN_CHECK(bgl != nullptr);
    return bgl;
}

const BindGroupLayoutInternalBase* PipelineLayoutBase::GetBindGroupLayout(
    BindGroupIndex group) const {
    DAWN_CHECK(!IsError());
    return GetFrontendBindGroupLayout(group)->GetInternalBindGroupLayout();
}

BindGroupLayoutInternalBase* PipelineLayoutBase::GetBindGroupLayout(BindGroupIndex group) {
    DAWN_CHECK(!IsError());
    return GetFrontendBindGroupLayout(group)->GetInternalBindGroupLayout();
}

const BindGroupMask& PipelineLayoutBase::GetBindGroupLayoutsMask() const {
    DAWN_CHECK(!IsError());
    return mMask;
}

bool PipelineLayoutBase::HasPixelLocalStorage() const {
    DAWN_CHECK(!IsError());
    return mHasPLS;
}

const std::vector<wgpu::TextureFormat>& PipelineLayoutBase::GetStorageAttachmentSlots() const {
    DAWN_CHECK(!IsError());
    return mStorageAttachmentSlots;
}

bool PipelineLayoutBase::HasAnyStorageAttachments() const {
    DAWN_CHECK(!IsError());

    for (auto format : mStorageAttachmentSlots) {
        if (format != wgpu::TextureFormat::Undefined) {
            return true;
        }
    }
    return false;
}

bool PipelineLayoutBase::HasExternalTextures() const {
    DAWN_CHECK(!IsError());

    for (BindGroupIndex g : mMask) {
        if (mBindGroupLayouts[g]->GetInternalBindGroupLayout()->GetExternalTextureCount() != 0) {
            return true;
        }
    }
    return false;
}

bool PipelineLayoutBase::HasAPIStaticSamplers() const {
    DAWN_CHECK(!IsError());

    for (BindGroupIndex g : mMask) {
        if (mBindGroupLayouts[g]->GetInternalBindGroupLayout()->GetAPIStaticSamplerCount() != 0) {
            return true;
        }
    }
    return false;
}

BindGroupMask PipelineLayoutBase::InheritedGroupsMask(const PipelineLayoutBase* other) const {
    DAWN_CHECK(!IsError());
    return {(1 << static_cast<uint32_t>(GroupsInheritUpTo(other))) - 1u};
}

BindGroupIndex PipelineLayoutBase::GroupsInheritUpTo(const PipelineLayoutBase* other) const {
    DAWN_CHECK(!IsError());

    for (BindGroupIndex i(0u); i < kMaxBindGroupsTyped; ++i) {
        if (!mMask[i] || mBindGroupLayouts[i].Get() != other->mBindGroupLayouts[i].Get()) {
            return i;
        }
    }
    return kMaxBindGroupsTyped;
}

size_t PipelineLayoutBase::ComputeContentHash() {
    ObjectContentHasher recorder;
    recorder.Record(mMask);

    for (BindGroupIndex group : mMask) {
        recorder.Record(GetBindGroupLayout(group)->GetContentHash());
    }

    // Hash the PLS state
    recorder.Record(mHasPLS);
    for (wgpu::TextureFormat slotFormat : mStorageAttachmentSlots) {
        recorder.Record(slotFormat);
    }

    // Hash the immediate data range byte size
    recorder.Record(mImmediateDataRangeByteSize);

    // Hash the resource table state
    recorder.Record(mUsesResourceTable);

    return recorder.GetContentHash();
}

bool PipelineLayoutBase::EqualityFunc::operator()(const PipelineLayoutBase* a,
                                                  const PipelineLayoutBase* b) const {
    if (a->mMask != b->mMask) {
        return false;
    }

    for (BindGroupIndex group : a->mMask) {
        if (a->GetBindGroupLayout(group) != b->GetBindGroupLayout(group)) {
            return false;
        }
    }

    // Check PLS
    if (a->mHasPLS != b->mHasPLS) {
        return false;
    }
    if (a->mStorageAttachmentSlots.size() != b->mStorageAttachmentSlots.size()) {
        return false;
    }
    for (size_t i = 0; i < a->mStorageAttachmentSlots.size(); i++) {
        if (a->mStorageAttachmentSlots[i] != b->mStorageAttachmentSlots[i]) {
            return false;
        }
    }

    // Check immediate data range
    if (a->mImmediateDataRangeByteSize != b->mImmediateDataRangeByteSize) {
        return false;
    }

    // Check resource table
    if (a->mUsesResourceTable != b->mUsesResourceTable) {
        return false;
    }

    return true;
}

uint32_t PipelineLayoutBase::GetImmediateDataRangeByteSize() const {
    DAWN_CHECK(!IsError());
    return mImmediateDataRangeByteSize;
}

bool PipelineLayoutBase::UsesResourceTable() const {
    DAWN_CHECK(!IsError());
    return mUsesResourceTable;
}

}  // namespace dawn::native
