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

#include <algorithm>
#include <limits>
#include <variant>

#include "absl/container/flat_hash_map.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/ityp_bitset.h"
#include "src/dawn/native/Adapter.h"
#include "src/dawn/native/BindGroupLayout.h"
#include "src/dawn/native/BindGroupLayoutInternal.h"
#include "src/dawn/native/BindingInfo.h"
#include "src/dawn/native/Buffer.h"
#include "src/dawn/native/CommandValidation.h"
#include "src/dawn/native/Device.h"
#include "src/dawn/native/ExternalTexture.h"
#include "src/dawn/native/ObjectBase.h"
#include "src/dawn/native/Sampler.h"
#include "src/dawn/native/TexelBufferView.h"
#include "src/dawn/native/Texture.h"
#include "src/dawn/native/utils/NativeHelpers.h"
#include "src/utils/assert.h"
#include "src/utils/compiler.h"
#include "src/utils/numeric.h"

namespace dawn::native {

namespace {

// Helper functions to perform binding-type specific validation

MaybeValError ValidateBufferBinding(const DeviceBase* device,
                                    const BindGroupEntry& entry,
                                    const BufferBindingInfo& layout) {
    DAWN_INVALID_IF(entry.buffer == nullptr, "Binding entry buffer not set.");

    DAWN_INVALID_IF(entry.sampler != nullptr || entry.textureView != nullptr,
                    "Expected only buffer to be set for binding entry.");

    DAWN_INVALID_IF(entry.nextInChain != nullptr, "nextInChain must be nullptr.");

    DAWN_TRY(device->ValidateObject(entry.buffer));

    uint64_t bufferSize = entry.buffer->GetSize();

    // Handle wgpu::WholeSize, avoiding overflows.
    DAWN_INVALID_IF(entry.offset > bufferSize,
                    "Binding offset (%u) is larger than the size (%u) of %s.", entry.offset,
                    bufferSize, entry.buffer);

    uint64_t bindingSize =
        (entry.size == wgpu::kWholeSize) ? bufferSize - entry.offset : entry.size;

    DAWN_INVALID_IF(bindingSize > bufferSize,
                    "Binding size (%u) is larger than the size (%u) of %s.", bindingSize,
                    bufferSize, entry.buffer);

    DAWN_INVALID_IF(bindingSize == 0, "Binding size for %s is zero.", entry.buffer);

    // Note that no overflow can happen because we already checked that
    // bufferSize >= bindingSize
    DAWN_INVALID_IF(entry.offset > bufferSize - bindingSize,
                    "Binding range (offset: %u, size: %u) doesn't fit in the size (%u) of %s.",
                    entry.offset, bufferSize, bindingSize, entry.buffer);

    wgpu::BufferUsage requiredUsage;
    uint64_t requiredBindingAlignment;
    switch (layout.type) {
        case wgpu::BufferBindingType::Uniform:
            requiredUsage = wgpu::BufferUsage::Uniform;
            requiredBindingAlignment = device->GetLimits().v1.minUniformBufferOffsetAlignment;
            break;
        case wgpu::BufferBindingType::Storage:
        case wgpu::BufferBindingType::ReadOnlyStorage:
            requiredUsage = wgpu::BufferUsage::Storage;
            requiredBindingAlignment = device->GetLimits().v1.minStorageBufferOffsetAlignment;
            DAWN_INVALID_IF(
                bindingSize % 4 != 0,
                "Binding size (%u) of %s isn't a multiple of 4 when binding type is (%s).",
                bindingSize, entry.buffer, layout.type);
            break;
        case kInternalStorageBufferBinding:
            requiredUsage = kInternalStorageBuffer;
            requiredBindingAlignment = device->GetLimits().v1.minStorageBufferOffsetAlignment;
            break;
        case kInternalReadOnlyStorageBufferBinding:
            // This is needed for for some workarounds that read a buffer in shaders. The buffer
            // only needs kReadOnlyStorageBuffer usage in this case. Unlike the standard
            // wgpu::BufferBindingType::ReadOnlyStorage which requires the read-write Storage usage.
            // On some backends such as D3D11, using only kReadOnlyStorageBuffer usage could avoid
            // extra allocations.
            requiredUsage = kReadOnlyStorageBuffer;
            requiredBindingAlignment = device->GetLimits().v1.minStorageBufferOffsetAlignment;
            break;
        case wgpu::BufferBindingType::BindingNotUsed:
        case wgpu::BufferBindingType::Undefined:
            DAWN_UNREACHABLE();
    }

    DAWN_INVALID_IF(!IsAligned(static_cast<uint32_t>(entry.offset),
                               checked_cast<size_t>(requiredBindingAlignment)),
                    "Offset (%u) of %s does not satisfy the minimum %s alignment (%u).",
                    entry.offset, entry.buffer, layout.type, requiredBindingAlignment);

    DAWN_INVALID_IF(!(entry.buffer->GetInternalUsage() & requiredUsage),
                    "Binding usage (%s) of %s doesn't match expected usage (%s).",
                    entry.buffer->GetUsage(), entry.buffer, requiredUsage);

    DAWN_INVALID_IF(bindingSize < layout.minBindingSize,
                    "Binding size (%u) of %s is smaller than the minimum binding size (%u).",
                    bindingSize, entry.buffer, layout.minBindingSize);

    uint64_t maxUniformBufferBindingSize;
    uint64_t maxStorageBufferBindingSize;
    switch (layout.type) {
        case wgpu::BufferBindingType::Uniform:
            maxUniformBufferBindingSize = device->GetLimits().v1.maxUniformBufferBindingSize;
            DAWN_INVALID_IF(bindingSize > maxUniformBufferBindingSize,
                            "Binding size (%u) of %s is larger than the maximum uniform buffer "
                            "binding size (%u).%s",
                            bindingSize, entry.buffer, maxUniformBufferBindingSize,
                            DAWN_INCREASE_LIMIT_MESSAGE(device->GetAdapter()->GetLimits().v1,
                                                        maxUniformBufferBindingSize, bindingSize));
            break;
        case wgpu::BufferBindingType::Storage:
        case wgpu::BufferBindingType::ReadOnlyStorage:
        case kInternalStorageBufferBinding:
        case kInternalReadOnlyStorageBufferBinding:
            maxStorageBufferBindingSize = device->GetLimits().v1.maxStorageBufferBindingSize;
            DAWN_INVALID_IF(bindingSize > maxStorageBufferBindingSize,
                            "Binding size (%u) of %s is larger than the maximum storage buffer "
                            "binding size (%u).%s",
                            bindingSize, entry.buffer, maxStorageBufferBindingSize,
                            DAWN_INCREASE_LIMIT_MESSAGE(device->GetAdapter()->GetLimits().v1,
                                                        maxStorageBufferBindingSize, bindingSize));
            break;
        case wgpu::BufferBindingType::BindingNotUsed:
        case wgpu::BufferBindingType::Undefined:
            DAWN_UNREACHABLE();
    }

    return {};
}

MaybeValError ValidateTextureBindGroupEntry(const DeviceBase* device, const BindGroupEntry& entry) {
    DAWN_INVALID_IF(entry.textureView == nullptr, "Binding entry textureView not set.");

    DAWN_INVALID_IF(entry.sampler != nullptr || entry.buffer != nullptr,
                    "Expected only textureView to be set for binding entry.");

    DAWN_INVALID_IF(entry.nextInChain != nullptr, "nextInChain must be nullptr.");

    TextureViewBase* view = entry.textureView;
    DAWN_TRY(device->ValidateObject(view));

    Aspect aspect = view->GetAspects();
    DAWN_INVALID_IF(!HasOneBit(aspect), "Multiple aspects (%s) selected in %s.", aspect, view);

    return {};
}

MaybeValError ValidateCompatibilityModeTextureViewArrayLayer(DeviceBase* device,
                                                             const TextureViewBase* view,
                                                             const TextureBase* texture) {
    DAWN_INVALID_IF(
        view->GetBaseArrayLayer() != 0 || view->GetLayerCount() != texture->GetArrayLayers(),
        "Texture binding uses %s with baseArrayLayer (%u) and arrayLayerCount (%u), but must use "
        "all (%u) layers of %s in compatibility mode.",
        view, view->GetBaseArrayLayer(), view->GetLayerCount(), texture->GetArrayLayers(), texture);

    return {};
}

MaybeValError ValidateTextureBindingViewDimension(DeviceBase* device,
                                                  TextureViewBase* view,
                                                  TextureBase* texture) {
    if (!device->HasFlexibleTextureViews()) {
        DAWN_INVALID_IF(
            view->GetDimension() != texture->GetCompatibilityTextureBindingViewDimension(),
            "Dimension (%s) of %s must match textureBindingViewDimension (%s) of "
            "%s in compatibility mode.",
            view->GetDimension(), view, texture->GetCompatibilityTextureBindingViewDimension(),
            texture);

        DAWN_TRY(ValidateCompatibilityModeTextureViewArrayLayer(device, view, texture));
    }

    return {};
}

MaybeValError ValidateSampledTextureBinding(DeviceBase* device,
                                            const BindGroupEntry& entry,
                                            const TextureBindingInfo& layout,
                                            UsageValidationMode mode) {
    DAWN_TRY(ValidateTextureBindGroupEntry(device, entry));

    TextureViewBase* view = entry.textureView;
    TextureBase* texture = view->GetTexture();

    Aspect aspect = view->GetAspects();
    SampleTypeBit supportedTypes = texture->GetFormat().GetAspectInfo(aspect).supportedSampleTypes;

    DAWN_TRY(ValidateCanUseAs(view, wgpu::TextureUsage::TextureBinding, mode));

    DAWN_INVALID_IF(texture->IsMultisampledTexture() != layout.multisampled,
                    "Sample count (%u) of %s doesn't match expectation (multisampled: %d).",
                    texture->GetSampleCount(), texture, layout.multisampled);

    SampleTypeBit requiredType;
    if (layout.sampleType == kInternalResolveAttachmentSampleType) {
        // If the binding's sample type is kInternalResolveAttachmentSampleType,
        // then the supported types must contain float.
        requiredType = SampleTypeBit::UnfilterableFloat;
    } else {
        requiredType = SampleTypeToSampleTypeBit(layout.sampleType);
    }

    DAWN_INVALID_IF(!(supportedTypes & requiredType),
                    "None of the supported sample types (%s) of %s match the expected sample "
                    "types (%s).",
                    supportedTypes, texture, requiredType);

    DAWN_INVALID_IF(entry.textureView->GetDimension() != layout.viewDimension,
                    "Dimension (%s) of %s doesn't match the expected dimension (%s).",
                    entry.textureView->GetDimension(), entry.textureView, layout.viewDimension);

    DAWN_TRY(ValidateTextureBindingViewDimension(device, view, texture));

    return {};
}

MaybeValError ValidateTextureViewBindingUsedAsExternalTexture(DeviceBase* device,
                                                              const BindGroupEntry& entry) {
    // TODO(crbug.com/398752857): Error message should include that entry is neither an
    // ExternalTexture nor a TextureView when the layout contains an ExternalTexture entry.
    DAWN_TRY(ValidateTextureBindGroupEntry(device, entry));

    TextureViewBase* view = entry.textureView;
    TextureBase* texture = view->GetTexture();
    wgpu::TextureFormat format = view->GetFormat().format;

    DAWN_INVALID_IF(
        format != wgpu::TextureFormat::RGBA8Unorm && format != wgpu::TextureFormat::BGRA8Unorm &&
            format != wgpu::TextureFormat::RGBA16Float,
        "%s format (%s) is not %s, %s, or %s.", view, format, wgpu::TextureFormat::RGBA8Unorm,
        wgpu::TextureFormat::BGRA8Unorm, wgpu::TextureFormat::RGBA16Float);

    DAWN_INVALID_IF((view->GetUsage() & wgpu::TextureUsage::TextureBinding) == 0,
                    "%s usage (%s) doesn't include the required usage (%s)", view, view->GetUsage(),
                    wgpu::TextureUsage::TextureBinding);

    DAWN_INVALID_IF(view->GetDimension() != wgpu::TextureViewDimension::e2D,
                    "%s dimension (%s) is not 2D.", view, view->GetDimension());

    DAWN_INVALID_IF(view->GetLevelCount() > 1, "%s mip level count (%u) is not 1.", view,
                    view->GetLevelCount());

    DAWN_INVALID_IF(texture->GetSampleCount() != 1, "%s sample count (%u) is not 1.", texture,
                    texture->GetSampleCount());

    return {};
}

MaybeValError ValidateStorageTextureBinding(DeviceBase* device,
                                            const BindGroupEntry& entry,
                                            const StorageTextureBindingInfo& layout,
                                            UsageValidationMode mode) {
    DAWN_TRY(ValidateTextureBindGroupEntry(device, entry));

    TextureViewBase* view = entry.textureView;
    TextureBase* texture = view->GetTexture();

    DAWN_TRY(ValidateCanUseAs(view, wgpu::TextureUsage::StorageBinding, mode));

    DAWN_CHECK(!texture->IsMultisampledTexture());

    DAWN_INVALID_IF(texture->GetFormat().format != layout.format,
                    "Format (%s) of %s expected to be (%s).", texture->GetFormat().format, texture,
                    layout.format);

    DAWN_INVALID_IF(view->GetDimension() != layout.viewDimension,
                    "Dimension (%s) of %s doesn't match the expected dimension (%s).",
                    view->GetDimension(), entry.textureView, layout.viewDimension);

    DAWN_INVALID_IF(view->GetLevelCount() != 1, "mipLevelCount (%u) of %s expected to be 1.",
                    view->GetLevelCount(), view);

    // TODO(450506641): Precompute allowed usages of texture views (including swizzle identity
    // check) instead of recomputing.
    DAWN_INVALID_IF(!view->IsSwizzleIdentity(), "Swizzle of %s must be identity.", view);

    if (!device->HasFlexibleTextureViews()) {
        DAWN_TRY(ValidateCompatibilityModeTextureViewArrayLayer(device, view, texture));
    }

    DAWN_TRY(ValidateTextureBindingViewDimension(device, view, texture));

    return {};
}

MaybeValError ValidateTexelBufferBinding(DeviceBase* device,
                                         const UnpackedPtr<BindGroupEntry>& entry,
                                         const TexelBufferBindingInfo& layout,
                                         UsageValidationMode mode) {
    const TexelBufferBindingEntry* texelBufferEntry = entry.Get<TexelBufferBindingEntry>();
    DAWN_INVALID_IF(texelBufferEntry == nullptr, "Expected a texelBufferView.");

    DAWN_TRY(entry.ValidateSubset<TexelBufferBindingEntry>());
    DAWN_INVALID_IF(
        entry->buffer != nullptr || entry->sampler != nullptr || entry->textureView != nullptr,
        "Expected only texelBufferView to be set for binding entry.");

    DAWN_TRY(device->ValidateObject(texelBufferEntry->texelBufferView));

    BufferBase* buffer = texelBufferEntry->texelBufferView->GetBuffer();
    DAWN_TRY(ValidateCanUseAs(buffer, wgpu::BufferUsage::TexelBuffer));

    DAWN_INVALID_IF(texelBufferEntry->texelBufferView->GetFormat() != layout.format,
                    "Format (%s) of %s expected to be (%s).",
                    texelBufferEntry->texelBufferView->GetFormat(),
                    texelBufferEntry->texelBufferView, layout.format);

    if (layout.access == wgpu::TexelBufferAccess::ReadWrite) {
        DAWN_TRY(ValidateCanUseAs(buffer, wgpu::BufferUsage::Storage));
    }

    return {};
}

MaybeValError ValidateSamplerBinding(const DeviceBase* device,
                                     const BindGroupEntry& entry,
                                     const SamplerBindingInfo& layout) {
    DAWN_INVALID_IF(entry.sampler == nullptr, "Binding entry sampler not set.");

    DAWN_INVALID_IF(entry.sampler->IsYCbCr(),
                    "YCbCr sampler is incompatible with SamplerBindingLayout");

    DAWN_INVALID_IF(entry.textureView != nullptr || entry.buffer != nullptr,
                    "Expected only sampler to be set for binding entry.");

    DAWN_INVALID_IF(entry.nextInChain != nullptr, "nextInChain must be nullptr.");

    DAWN_TRY(device->ValidateObject(entry.sampler));

    switch (layout.type) {
        case wgpu::SamplerBindingType::NonFiltering:
            DAWN_INVALID_IF(entry.sampler->IsFiltering(),
                            "Filtering sampler %s is incompatible with non-filtering sampler "
                            "binding.",
                            entry.sampler);
            [[fallthrough]];
        case wgpu::SamplerBindingType::Filtering:
            DAWN_INVALID_IF(entry.sampler->IsComparison(),
                            "Comparison sampler %s is incompatible with non-comparison sampler "
                            "binding.",
                            entry.sampler);
            break;
        case wgpu::SamplerBindingType::Comparison:
            DAWN_INVALID_IF(!entry.sampler->IsComparison(),
                            "Non-comparison sampler %s is incompatible with comparison sampler "
                            "binding.",
                            entry.sampler);
            break;
        default:
            DAWN_UNREACHABLE();
            break;
    }

    return {};
}

MaybeValError ValidateExternalTextureBinding(DeviceBase* device,
                                             const UnpackedPtr<BindGroupEntry>& entry) {
    auto* externalTextureBindingEntry = entry.Get<ExternalTextureBindingEntry>();

    // It is possible to use texture views in lieu of external textures.
    if (externalTextureBindingEntry == nullptr) {
        return ValidateTextureViewBindingUsedAsExternalTexture(device, **entry);
    }

    DAWN_TRY(entry.ValidateSubset<ExternalTextureBindingEntry>());
    DAWN_INVALID_IF(
        entry->sampler != nullptr || entry->textureView != nullptr || entry->buffer != nullptr,
        "Expected only external texture to be set for binding entry.");
    return device->ValidateObject(externalTextureBindingEntry->externalTexture);
}

template <typename F>
void ForEachUnverifiedBufferBindingIndexImpl(const BindGroupLayoutInternalBase* bgl, F&& f) {
    uint32_t packedIndex = 0;
    for (BindingIndex bindingIndex : bgl->GetBufferIndices()) {
        const auto& bufferLayout =
            std::get<BufferBindingInfo>(bgl->GetBindingInfo(bindingIndex).bindingLayout);
        if (bufferLayout.minBindingSize == 0) {
            f(bindingIndex, packedIndex++);
        }
    }
}

MaybeValError ValidateStaticSamplersWithSampledTextures(
    const UnpackedPtr<BindGroupDescriptor>& descriptor,
    const BindGroupLayoutInternalBase* layout) {
    // Cache the position of all the sampled texture in descriptor->entries to later validate them
    // against their static sampler (if they are used with the static sampler).
    absl::flat_hash_map<BindingIndex, size_t> textureIndexToEntryIndex;
    for (auto [i, entry] : Enumerate(descriptor->entries)) {
        APIBindingIndex apiIndex = layout->GetBindingMap().at(BindingNumber(entry.binding));
        const auto& bindingInfo = layout->GetAPIBindingInfo(apiIndex);
        if (std::holds_alternative<TextureBindingInfo>(bindingInfo.bindingLayout)) {
            textureIndexToEntryIndex[layout->AsBindingIndex(apiIndex)] = i;
        }
    }

    // Gather the indices of YCbCr textures sampled by a static sampler.
    ityp::bitset<size_t, kMaxBindingsPerPipelineLayout> sampledYcbcrTextures;
    for (BindingIndex samplerIndex : layout->GetStaticSamplerIndices()) {
        const BindingInfo& bindingInfo = layout->GetBindingInfo(samplerIndex);
        const auto& staticSamplerLayout =
            std::get<StaticSamplerBindingInfo>(bindingInfo.bindingLayout);
        if (staticSamplerLayout.use != StaticSamplerUse::SingleTextureYCbCr) {
            continue;
        }

        size_t textureEntryIndex =
            textureIndexToEntryIndex.at(staticSamplerLayout.sampledTextureIndex);

        const SamplerBase* sampler = staticSamplerLayout.sampler.Get();
        const TextureViewBase* textureView = descriptor->entries[textureEntryIndex].textureView;

        // Compare static sampler and sampled textures to make sure they are compatible.
        if (sampler->IsYCbCr()) {
            DAWN_INVALID_IF(!textureView->IsYCbCr(),
                            "YCbCr static sampler %s at binding (%u) samples a non-YCbCr %s.",
                            sampler, bindingInfo.binding, textureView);

            // YCbCr views can be created without a YCbCrDescriptor but that means they can only be
            // used with ExternalTextures.
            DAWN_INVALID_IF(!textureView->HasYCbCrDescriptor(),
                            "YCbCr static sampler %s at binding (%u) samples a YCbCr %s with "
                            "implicit YCbCr info.",
                            sampler, bindingInfo.binding, textureView);

            // Filterability of YCbCr textures is per-object so we don't check with the sampleType
            // but instead check against the static sampler it will be used with.
            DAWN_INVALID_IF(sampler->IsFiltering() && !textureView->IsYCbCrFilterable(),
                            "YCbCr static sampler %s at binding (%u) is filtering but samples an "
                            "unfilterable YCbCr %s.",
                            sampler, bindingInfo.binding, textureView);

            sampledYcbcrTextures.set(textureEntryIndex);
        } else {
            DAWN_INVALID_IF(textureView->IsYCbCr(),
                            "Non-YCbCr static sampler at binding (%u) samples a YCbCr texture.",
                            bindingInfo.binding);
        }
    }

    // Validate that all YCbCr texture entries are sampled by a static sampler.
    const auto& bindingMap = layout->GetBindingMap();
    for (auto [i, entry] : Enumerate(descriptor->entries)) {
        const BindingInfo& bindingInfo =
            layout->GetAPIBindingInfo(bindingMap.at(BindingNumber(entry.binding)));
        if (std::holds_alternative<TextureBindingInfo>(bindingInfo.bindingLayout) &&
            entry.textureView && entry.textureView->IsYCbCr()) {
            DAWN_INVALID_IF(!sampledYcbcrTextures.test(static_cast<uint32_t>(i)),
                            "YCbCr texture at binding (%u) is not sampled by a static sampler.",
                            entry.binding);
        }
    }

    return {};
}

}  // anonymous namespace

ResultOrValError<UnpackedPtr<BindGroupDescriptor>> ValidateBindGroupDescriptor(
    DeviceBase* device,
    const BindGroupDescriptor* descriptorChain,
    UsageValidationMode mode) {
    UnpackedPtr<BindGroupDescriptor> descriptor;
    DAWN_TRY_ASSIGN(descriptor, ValidateAndUnpack(descriptorChain));

    DAWN_TRY(device->ValidateObject(descriptor->layout));
    BindGroupLayoutInternalBase* layout = descriptor->layout->GetInternalBindGroupLayout();
    const BindGroupLayoutInternalBase::BindingMap& bindingMap = layout->GetBindingMap();

    // Validate individual entries.
    bool needsCrossBindingValidation = layout->NeedsCrossBindingValidation();
    // TODO(https://issues.chromium.org/448578977): Use a more optimized type as 1000 bits on the
    // stack is a bit much.
    ityp::bitset<BindingNumber, kMaxBindingsPerBindGroup> bindingsSet;
    for (auto [i, entry] : Enumerate(descriptor->entries)) {
        BindingNumber binding = BindingNumber(entry.binding);

        // Check that the entry exists in the BGL and get its info.
        const auto& it = bindingMap.find(binding);
        DAWN_INVALID_IF(it == bindingMap.end(),
                        "In entries[%u], binding index %u not present in the bind group layout."
                        "\nExpected layout: %s",
                        i, binding, layout->EntriesToString());
        const BindingInfo& bindingInfo = layout->GetAPIBindingInfo(it->second);

        // Check for redundant entries.
        DAWN_INVALID_IF(bindingsSet[binding],
                        "In entries[%u], binding index %u already used by a previous entry", i,
                        binding);
        bindingsSet.set(binding);

        // Below this block we validate entries based on the bind group layout, in which
        // external textures have been expanded into their underlying contents. For this reason
        // we must identify external texture binding entries by checking the bind group entry
        // itself.
        // TODO(42240282): Store external textures in
        // BindGroupLayoutBase::BindingDataPointers::bindings so checking external textures can
        // be moved in the switch below.
        UnpackedPtr<BindGroupEntry> unpacked;
        DAWN_TRY_ASSIGN(unpacked, ValidateAndUnpack(&entry));

        // Perform binding-type specific validation.
        DAWN_TRY_CONTEXT(
            MatchVariant(
                bindingInfo.bindingLayout,
                [&](const BufferBindingInfo& layout) -> MaybeValError {
                    // TODO(dawn:1485): Validate buffer binding with usage validation mode.
                    return ValidateBufferBinding(device, entry, layout);
                },
                [&](const TextureBindingInfo& layout) -> MaybeValError {
                    DAWN_TRY(ValidateSampledTextureBinding(device, entry, layout, mode));

                    if (entry.textureView->IsYCbCr()) {
                        // Need to validate that the YCbCr texture is statically sampled.
                        needsCrossBindingValidation = true;
                    }
                    return {};
                },
                [&](const StorageTextureBindingInfo& layout) -> MaybeValError {
                    return ValidateStorageTextureBinding(device, entry, layout, mode);
                },
                [&](const TexelBufferBindingInfo& layout) -> MaybeValError {
                    return ValidateTexelBufferBinding(device, unpacked, layout, mode);
                },
                [&](const SamplerBindingInfo& layout) -> MaybeValError {
                    return ValidateSamplerBinding(device, entry, layout);
                },
                [&](const StaticSamplerBindingInfo& layout) -> MaybeValError {
                    return DAWN_VALIDATION_ERROR("An entry is provided for a static sampler.");
                },
                [&](const ExternalTextureBindingInfo& layout) -> MaybeValError {
                    return ValidateExternalTextureBinding(device, unpacked);
                },

                [](const InputAttachmentBindingInfo&) -> MaybeValError {
                    // Internal use only. No validation.
                    return {};
                }),
            "validating entries[%u] against %s.", i, bindingInfo);
    }

    // Check that we have all the required entries.
    const uint32_t expectedEntryCount = layout->GetBindingCountForBindGroupCreation();

    DAWN_INVALID_IF(
        descriptor->entries.size() != expectedEntryCount,
        "Number of entries (%u) did not match the expected number of entries (%u) for %s."
        "\nExpected layout: %s",
        descriptor->entries.size(), expectedEntryCount, layout, layout->EntriesToString());

    // This should always be true because
    //  - numBindings has to match between the bind group and its layout.
    //  - Each binding must be set at most once
    //
    // We don't validate the equality because it wouldn't be possible to cover it with a test.
    DAWN_CHECK(bindingsSet.count() == expectedEntryCount);

    if (needsCrossBindingValidation) {
        // This additional validation is only needed when there are static samplers used with a
        // single texture binding and/or there are YCbCr textures.
        DAWN_TRY(ValidateStaticSamplersWithSampledTextures(descriptor, layout));
    }

    return descriptor;
}

// BindGroup

BindGroupBase::BindGroupBase(DeviceBase* device,
                             const UnpackedPtr<BindGroupDescriptor>& descriptor,
                             void* bindingDataStart)
    : ApiObjectBase(device, descriptor->label),
      mLayout(descriptor->layout),
      mBindingData(GetLayout()->ComputeBindingDataPointers(bindingDataStart)) {
    GetObjectTrackingList()->Track(this);
}

MaybeError BindGroupBase::Initialize(const UnpackedPtr<BindGroupDescriptor>& descriptor) {
    BindGroupLayoutInternalBase* layout = GetLayout();

    for (BindingIndex i{0u}; i < layout->GetBindingCount(); ++i) {
        // TODO(enga): Shouldn't be needed when bindings are tightly packed.
        // This is to fill Ref<ObjectBase> holes with nullptrs.
        new (&mBindingData.bindings[i]) Ref<ObjectBase>();
    }

    // Fill mBoundTextures with nullptr since these binding entries can possibly be bound without an
    // external texture.
    mBoundExternalTextures.resize(layout->GetExternalTextureCount(), nullptr);

    // Gather bindings.
    for (const BindGroupEntry& entryChain : descriptor->entries) {
        UnpackedPtr<BindGroupEntry> entry = Unpack(&entryChain);
        BindingNumber binding = BindingNumber(entry->binding);
        APIBindingIndex apiBindingIndex = layout->GetAPIBindingIndex(binding);

        DAWN_TRY(MatchVariant(
            layout->GetAPIBindingInfo(apiBindingIndex).bindingLayout,
            [&](const BufferBindingInfo&) -> MaybeError {
                BindingIndex bindingIndex = layout->AsBindingIndex(apiBindingIndex);
                DAWN_CHECK(mBindingData.bindings[bindingIndex] == nullptr);
                mBindingData.bindings[bindingIndex] = entry->buffer;
                mBindingData.bufferData[bindingIndex].offset = entry->offset;
                uint64_t bufferSize = (entry->size == wgpu::kWholeSize)
                                          ? entry->buffer->GetSize() - entry->offset
                                          : entry->size;
                mBindingData.bufferData[bindingIndex].size = bufferSize;
                return {};
            },

            [&](const TextureBindingInfo&) -> MaybeError {
                BindingIndex bindingIndex = layout->AsBindingIndex(apiBindingIndex);
                DAWN_CHECK(mBindingData.bindings[bindingIndex] == nullptr);
                mBindingData.bindings[bindingIndex] = entry->textureView;
                return {};
            },
            [&](const StorageTextureBindingInfo&) -> MaybeError {
                BindingIndex bindingIndex = layout->AsBindingIndex(apiBindingIndex);
                DAWN_CHECK(mBindingData.bindings[bindingIndex] == nullptr);
                mBindingData.bindings[bindingIndex] = entry->textureView;
                return {};
            },
            [&](const InputAttachmentBindingInfo&) -> MaybeError {
                BindingIndex bindingIndex = layout->AsBindingIndex(apiBindingIndex);
                DAWN_CHECK(mBindingData.bindings[bindingIndex] == nullptr);
                mBindingData.bindings[bindingIndex] = entry->textureView;
                return {};
            },
            [&](const SamplerBindingInfo&) -> MaybeError {
                BindingIndex bindingIndex = layout->AsBindingIndex(apiBindingIndex);
                DAWN_CHECK(mBindingData.bindings[bindingIndex] == nullptr);
                mBindingData.bindings[bindingIndex] = entry->sampler;
                return {};
            },
            [&](const TexelBufferBindingInfo&) -> MaybeError {
                BindingIndex bindingIndex = layout->AsBindingIndex(apiBindingIndex);
                DAWN_CHECK(mBindingData.bindings[bindingIndex] == nullptr);
                auto* texelBufferBindingEntry = entry.Get<TexelBufferBindingEntry>();
                mBindingData.bindings[bindingIndex] = texelBufferBindingEntry->texelBufferView;
                return {};
            },

            [&](const ExternalTextureBindingInfo& info) -> MaybeError {
                // Here we unpack external texture bindings into multiple additional bindings for
                // the external texture's contents. New binding locations previously determined in
                // the bind group layout are created in this bind group and filled with the external
                // texture's underlying resources.
                if (auto* externalTextureBindingEntry = entry.Get<ExternalTextureBindingEntry>()) {
                    const auto& externalTextureMap = layout->GetBoundExternalTextureMap();
                    mBoundExternalTextures[externalTextureMap.at(apiBindingIndex)] =
                        externalTextureBindingEntry->externalTexture;

                    DAWN_CHECK(mBindingData.bindings[info.plane0] == nullptr);
                    mBindingData.bindings[info.plane0] =
                        externalTextureBindingEntry->externalTexture->GetTextureViews()[0];

                    DAWN_CHECK(mBindingData.bindings[info.plane1] == nullptr);
                    mBindingData.bindings[info.plane1] =
                        externalTextureBindingEntry->externalTexture->GetTextureViews()[1];

                    DAWN_CHECK(mBindingData.bindings[info.metadata] == nullptr);
                    mBindingData.bindings[info.metadata] =
                        externalTextureBindingEntry->externalTexture->GetParamsBuffer();
                    mBindingData.bufferData[info.metadata].offset = 0;
                    mBindingData.bufferData[info.metadata].size =
                        sizeof(dawn::native::ExternalTextureParams);
                    return {};
                }

                // If this is for a texture view that is used as an external texture, we need to
                // also provide placeholder for the second plane and a parameter buffer.
                DAWN_CHECK(entry->textureView != nullptr);

                DAWN_CHECK(mBindingData.bindings[info.plane0] == nullptr);
                mBindingData.bindings[info.plane0] = entry->textureView;

                DAWN_CHECK(mBindingData.bindings[info.plane1] == nullptr);
                DAWN_TRY_ASSIGN(mBindingData.bindings[info.plane1],
                                GetDevice()->GetOrCreatePlaceholderTextureViewForExternalTexture());

                DAWN_CHECK(mBindingData.bindings[info.metadata] == nullptr);
                Ref<BufferBase> paramsBuffer;
                DAWN_TRY_ASSIGN(paramsBuffer,
                                MakeParamsBufferForSimpleView(GetDevice(), entry->textureView));
                mBindingData.bindings[info.metadata] = paramsBuffer;
                mBindingData.bufferData[info.metadata].offset = 0;
                mBindingData.bufferData[info.metadata].size = paramsBuffer->GetSize();
                return {};
            },

            [](const StaticSamplerBindingInfo&) -> MaybeError { DAWN_UNREACHABLE(); }));
    }

    ForEachUnverifiedBufferBindingIndexImpl(layout,
                                            [&](BindingIndex bindingIndex, uint32_t packedIndex) {
                                                mBindingData.unverifiedBufferSizes[packedIndex] =
                                                    mBindingData.bufferData[bindingIndex].size;
                                            });

    DAWN_TRY(InitializeImpl());

    return {};
}

BindGroupBase::~BindGroupBase() = default;

void BindGroupBase::DestroyImpl(DestroyReason reason) {
    if (mLayout != nullptr) {
        DAWN_CHECK(!IsError());
        for (BindingIndex i{0u}; i < GetLayout()->GetBindingCount(); ++i) {
            mBindingData.bindings[i].~Ref<ObjectBase>();
        }
    }
}

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

// static
Ref<BindGroupBase> BindGroupBase::MakeError(DeviceBase* device, StringView label) {
    class ErrorBindGroupBase final : public BindGroupBase {
      public:
        explicit ErrorBindGroupBase(DeviceBase* device, StringView label)
            : BindGroupBase(device, ObjectBase::kError, label) {}
        MaybeError InitializeImpl() override { DAWN_UNREACHABLE(); }
    };

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

ObjectType BindGroupBase::GetType() const {
    return ObjectType::BindGroup;
}

BindGroupLayoutBase* BindGroupBase::GetFrontendLayout() {
    DAWN_CHECK(!IsError());
    return mLayout.Get();
}

const BindGroupLayoutBase* BindGroupBase::GetFrontendLayout() const {
    DAWN_CHECK(!IsError());
    return mLayout.Get();
}

BindGroupLayoutInternalBase* BindGroupBase::GetLayout() {
    DAWN_ASSERT(mLayout != nullptr);
    return mLayout->GetInternalBindGroupLayout();
}

const BindGroupLayoutInternalBase* BindGroupBase::GetLayout() const {
    DAWN_ASSERT(mLayout != nullptr);
    return mLayout->GetInternalBindGroupLayout();
}

const ityp::span<uint32_t, uint64_t>& BindGroupBase::GetUnverifiedBufferSizes() const {
    DAWN_CHECK(!IsError());
    return mBindingData.unverifiedBufferSizes;
}

BufferBase* BindGroupBase::GetBindingAsBuffer(BindingIndex bindingIndex) const {
    DAWN_CHECK(!IsError());
    const BindGroupLayoutInternalBase* layout = GetLayout();
    DAWN_CHECK(bindingIndex < layout->GetBindingCount());
    DAWN_CHECK(std::holds_alternative<BufferBindingInfo>(
        layout->GetBindingInfo(bindingIndex).bindingLayout));
    return static_cast<BufferBase*>(mBindingData.bindings[bindingIndex].Get());
}

SamplerBase* BindGroupBase::GetBindingAsSampler(BindingIndex bindingIndex) const {
    DAWN_CHECK(!IsError());
    const BindGroupLayoutInternalBase* layout = GetLayout();
    DAWN_CHECK(bindingIndex < layout->GetBindingCount());
    DAWN_CHECK(std::holds_alternative<SamplerBindingInfo>(
        layout->GetBindingInfo(bindingIndex).bindingLayout));
    return static_cast<SamplerBase*>(mBindingData.bindings[bindingIndex].Get());
}

TextureViewBase* BindGroupBase::GetBindingAsTextureView(BindingIndex bindingIndex) const {
    DAWN_CHECK(!IsError());
    const BindGroupLayoutInternalBase* layout = GetLayout();
    DAWN_CHECK(bindingIndex < layout->GetBindingCount());
    DAWN_CHECK(std::holds_alternative<TextureBindingInfo>(
                   layout->GetBindingInfo(bindingIndex).bindingLayout) ||
               std::holds_alternative<StorageTextureBindingInfo>(
                   layout->GetBindingInfo(bindingIndex).bindingLayout) ||
               std::holds_alternative<InputAttachmentBindingInfo>(
                   layout->GetBindingInfo(bindingIndex).bindingLayout));
    return static_cast<TextureViewBase*>(mBindingData.bindings[bindingIndex].Get());
}

BufferBinding BindGroupBase::GetBindingAsBufferBinding(BindingIndex bindingIndex) const {
    DAWN_CHECK(!IsError());
    return {GetBindingAsBuffer(bindingIndex), mBindingData.bufferData[bindingIndex].offset,
            mBindingData.bufferData[bindingIndex].size};
}

TexelBufferViewBase* BindGroupBase::GetBindingAsTexelBufferView(BindingIndex bindingIndex) const {
    DAWN_CHECK(!IsError());
    const BindGroupLayoutInternalBase* layout = GetLayout();
    DAWN_CHECK(bindingIndex < layout->GetBindingCount());
    DAWN_CHECK(std::holds_alternative<TexelBufferBindingInfo>(
        layout->GetBindingInfo(bindingIndex).bindingLayout));
    return static_cast<TexelBufferViewBase*>(mBindingData.bindings[bindingIndex].Get());
}

const std::vector<Ref<ExternalTextureBase>>& BindGroupBase::GetBoundExternalTextures() const {
    DAWN_CHECK(!IsError());
    return mBoundExternalTextures;
}

Ref<ExternalTextureBase> BindGroupBase::GetBoundExternalTexture(
    APIBindingIndex bindingIndex) const {
    DAWN_CHECK(!IsError());
    DAWN_CHECK(GetLayout()->GetBoundExternalTextureMap().count(bindingIndex) == 1);

    size_t etIndex = GetLayout()->GetBoundExternalTextureMap().at(bindingIndex);
    return mBoundExternalTextures[etIndex];
}

void BindGroupBase::ForEachUnverifiedBufferBindingIndex(
    std::function<void(BindingIndex, uint32_t)> fn) const {
    ForEachUnverifiedBufferBindingIndexImpl(GetLayout(), fn);
}

}  // namespace dawn::native
