// Copyright 2019 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 "dawn/native/CommandValidation.h"

#include <algorithm>
#include <limits>
#include <sstream>
#include <string>
#include <utility>

#include "dawn/common/BitSetIterator.h"
#include "dawn/common/Numeric.h"
#include "dawn/native/BindGroup.h"
#include "dawn/native/Buffer.h"
#include "dawn/native/CommandBufferStateTracker.h"
#include "dawn/native/Commands.h"
#include "dawn/native/Device.h"
#include "dawn/native/Instance.h"
#include "dawn/native/PassResourceUsage.h"
#include "dawn/native/PhysicalDevice.h"
#include "dawn/native/QuerySet.h"
#include "dawn/native/RenderBundle.h"
#include "dawn/native/RenderPipeline.h"
#include "dawn/native/ValidationUtils_autogen.h"

namespace dawn::native {

// Performs validation of the "synchronization scope" rules of WebGPU.
MaybeError ValidateSyncScopeResourceUsage(const SyncScopeResourceUsage& scope) {
    // Buffers can only be used as single-write or multiple read.
    for (size_t i = 0; i < scope.bufferSyncInfos.size(); ++i) {
        const wgpu::BufferUsage usage = scope.bufferSyncInfos[i].usage;
        bool readOnly = IsSubset(usage, kReadOnlyBufferUsages);
        bool singleUse = wgpu::HasZeroOrOneBits(usage);

        DAWN_INVALID_IF(!readOnly && !singleUse,
                        "%s usage (%s) includes writable usage and another usage in the same "
                        "synchronization scope.",
                        scope.buffers[i], usage);
    }

    // Check that every single subresource is used as either a single-write usage or a
    // combination of readonly usages.
    for (size_t i = 0; i < scope.textureSyncInfos.size(); ++i) {
        const TextureSubresourceSyncInfo& textureSyncInfo = scope.textureSyncInfos[i];
        DAWN_TRY(textureSyncInfo.Iterate(
            [&](const SubresourceRange&, const TextureSyncInfo& syncInfo) -> MaybeError {
                bool readOnly = IsSubset(syncInfo.usage, kReadOnlyTextureUsages);
                bool singleUse = wgpu::HasZeroOrOneBits(syncInfo.usage);
                if (readOnly || singleUse) {
                    return {};
                }
                // kResolveTextureLoadAndStoreUsages are kResolveAttachmentLoadingUsage &
                // RenderAttachment usage used in the same pass.
                // This is accepted because kResolveAttachmentLoadingUsage is an internal loading
                // operation for blitting a resolve target to an MSAA attachment. And there won't be
                // and read-after-write hazard.
                if (syncInfo.usage == kResolveTextureLoadAndStoreUsages) {
                    return {};
                }
                return DAWN_VALIDATION_ERROR(
                    "%s usage (%s) includes writable usage and another usage in the same "
                    "synchronization scope.",
                    scope.textures[i], syncInfo.usage);
            }));
    }
    return {};
}

MaybeError ValidateTimestampQuery(const DeviceBase* device,
                                  const QuerySetBase* querySet,
                                  uint32_t queryIndex,
                                  Feature requiredFeature) {
    DAWN_TRY(device->ValidateObject(querySet));

    DAWN_INVALID_IF(
        !device->HasFeature(requiredFeature),
        "Timestamp queries used without the %s feature enabled.",
        device->GetPhysicalDevice()->GetInstance()->GetFeatureInfo(ToAPI(requiredFeature))->name);

    DAWN_INVALID_IF(querySet->GetQueryType() != wgpu::QueryType::Timestamp,
                    "The type of %s is not %s.", querySet, wgpu::QueryType::Timestamp);

    DAWN_INVALID_IF(queryIndex >= querySet->GetQueryCount(),
                    "Query index (%u) exceeds the number of queries (%u) in %s.", queryIndex,
                    querySet->GetQueryCount(), querySet);

    return {};
}

MaybeError ValidatePassTimestampWrites(const DeviceBase* device,
                                       const QuerySetBase* querySet,
                                       uint32_t beginningOfPassWriteIndex,
                                       uint32_t endOfPassWriteIndex) {
    DAWN_TRY(device->ValidateObject(querySet));

    DAWN_INVALID_IF(!device->HasFeature(Feature::TimestampQuery),
                    "Timestamp queries used without the timestamp-query feature enabled.");

    DAWN_INVALID_IF(querySet->GetQueryType() != wgpu::QueryType::Timestamp,
                    "The type of %s is not %s.", querySet, wgpu::QueryType::Timestamp);

    if (beginningOfPassWriteIndex != wgpu::kQuerySetIndexUndefined) {
        DAWN_INVALID_IF(beginningOfPassWriteIndex >= querySet->GetQueryCount(),
                        "beginningOfPassWriteIndex (%u) exceeds the number of queries (%u) in %s.",
                        beginningOfPassWriteIndex, querySet->GetQueryCount(), querySet);
    }
    if (endOfPassWriteIndex != wgpu::kQuerySetIndexUndefined) {
        DAWN_INVALID_IF(endOfPassWriteIndex >= querySet->GetQueryCount(),
                        "endOfPassWriteIndex (%u) exceeds the number of queries (%u) in %s.",
                        endOfPassWriteIndex, querySet->GetQueryCount(), querySet);
    }

    DAWN_INVALID_IF(beginningOfPassWriteIndex == wgpu::kQuerySetIndexUndefined &&
                        endOfPassWriteIndex == wgpu::kQuerySetIndexUndefined,
                    "Both beginningOfPassWriteIndex and endOfPassWriteIndex are undefined.");

    DAWN_INVALID_IF(beginningOfPassWriteIndex == endOfPassWriteIndex,
                    "beginningOfPassWriteIndex (%u) is equal to endOfPassWriteIndex (%u).",
                    beginningOfPassWriteIndex, endOfPassWriteIndex);

    return {};
}

MaybeError ValidateWriteBuffer(const DeviceBase* device,
                               const BufferBase* buffer,
                               uint64_t bufferOffset,
                               uint64_t size) {
    DAWN_TRY(device->ValidateObject(buffer));

    DAWN_INVALID_IF(bufferOffset % 4 != 0, "BufferOffset (%u) is not a multiple of 4.",
                    bufferOffset);

    DAWN_INVALID_IF(size % 4 != 0, "Size (%u) is not a multiple of 4.", size);

    uint64_t bufferSize = buffer->GetSize();
    DAWN_INVALID_IF(bufferOffset > bufferSize || size > (bufferSize - bufferOffset),
                    "Write range (bufferOffset: %u, size: %u) does not fit in %s size (%u).",
                    bufferOffset, size, buffer, bufferSize);

    DAWN_TRY(ValidateCanUseAs(buffer, wgpu::BufferUsage::CopyDst));

    return {};
}

bool IsRangeOverlapped(uint32_t startA, uint32_t startB, uint32_t length) {
    if (length < 1) {
        return false;
    }
    return RangesOverlap<uint64_t>(
        static_cast<uint64_t>(startA),
        static_cast<uint64_t>(startA) + static_cast<uint64_t>(length) - 1,
        static_cast<uint64_t>(startB),
        static_cast<uint64_t>(startB) + static_cast<uint64_t>(length) - 1);
}

ResultOrError<uint64_t> ComputeRequiredBytesInCopy(const TexelBlockInfo& blockInfo,
                                                   const Extent3D& copySize,
                                                   uint32_t bytesPerRow,
                                                   uint32_t rowsPerImage) {
    DAWN_ASSERT(copySize.width % blockInfo.width == 0);
    DAWN_ASSERT(copySize.height % blockInfo.height == 0);
    uint32_t widthInBlocks = copySize.width / blockInfo.width;
    uint32_t heightInBlocks = copySize.height / blockInfo.height;
    uint64_t bytesInLastRow = Safe32x32(widthInBlocks, blockInfo.byteSize);

    if (copySize.depthOrArrayLayers == 0) {
        return 0;
    }

    // Check for potential overflows for the rest of the computations. We have the following
    // inequalities:
    //
    //   bytesInLastRow <= bytesPerRow
    //   heightInBlocks <= rowsPerImage
    //
    // So:
    //
    //   bytesInLastImage  = bytesPerRow * (heightInBlocks - 1) + bytesInLastRow
    //                    <= bytesPerRow * heightInBlocks
    //                    <= bytesPerRow * rowsPerImage
    //                    <= bytesPerImage
    //
    // This means that if the computation of depth * bytesPerImage doesn't overflow, none of the
    // computations for requiredBytesInCopy will. (and it's not a very pessimizing check)
    DAWN_ASSERT(copySize.depthOrArrayLayers <= 1 || (bytesPerRow != wgpu::kCopyStrideUndefined &&
                                                     rowsPerImage != wgpu::kCopyStrideUndefined));
    uint64_t bytesPerImage = Safe32x32(bytesPerRow, rowsPerImage);
    DAWN_INVALID_IF(
        bytesPerImage > std::numeric_limits<uint64_t>::max() / copySize.depthOrArrayLayers,
        "The number of bytes per image (%u) exceeds the maximum (%u) when copying %u images.",
        bytesPerImage, std::numeric_limits<uint64_t>::max() / copySize.depthOrArrayLayers,
        copySize.depthOrArrayLayers);

    uint64_t requiredBytesInCopy = bytesPerImage * (copySize.depthOrArrayLayers - 1);
    if (heightInBlocks > 0) {
        DAWN_ASSERT(heightInBlocks <= 1 || bytesPerRow != wgpu::kCopyStrideUndefined);
        uint64_t bytesInLastImage = Safe32x32(bytesPerRow, heightInBlocks - 1) + bytesInLastRow;
        requiredBytesInCopy += bytesInLastImage;
    }
    return requiredBytesInCopy;
}

MaybeError ValidateCopySizeFitsInBuffer(const Ref<BufferBase>& buffer,
                                        uint64_t offset,
                                        uint64_t size,
                                        BufferSizeType checkBufferSizeType) {
    uint64_t bufferSize = 0;
    switch (checkBufferSizeType) {
        case BufferSizeType::Size:
            bufferSize = buffer->GetSize();
            break;
        case BufferSizeType::AllocatedSize:
            bufferSize = buffer->GetAllocatedSize();
            break;
    }
    bool fitsInBuffer = offset <= bufferSize && (size <= (bufferSize - offset));
    DAWN_INVALID_IF(!fitsInBuffer,
                    "Copy range (offset: %u, size: %u) does not fit in %s size (%u).", offset, size,
                    buffer.Get(), bufferSize);

    return {};
}

// Replace wgpu::kCopyStrideUndefined with real values, so backends don't have to think about
// it.
void ApplyDefaultTextureDataLayoutOptions(TextureDataLayout* layout,
                                          const TexelBlockInfo& blockInfo,
                                          const Extent3D& copyExtent) {
    DAWN_ASSERT(layout != nullptr);
    DAWN_ASSERT(copyExtent.height % blockInfo.height == 0);
    uint32_t heightInBlocks = copyExtent.height / blockInfo.height;

    if (layout->bytesPerRow == wgpu::kCopyStrideUndefined) {
        DAWN_ASSERT(copyExtent.width % blockInfo.width == 0);
        uint32_t widthInBlocks = copyExtent.width / blockInfo.width;
        uint32_t bytesInLastRow = widthInBlocks * blockInfo.byteSize;

        DAWN_ASSERT(heightInBlocks <= 1 && copyExtent.depthOrArrayLayers <= 1);
        layout->bytesPerRow = Align(bytesInLastRow, kTextureBytesPerRowAlignment);
    }
    if (layout->rowsPerImage == wgpu::kCopyStrideUndefined) {
        DAWN_ASSERT(copyExtent.depthOrArrayLayers <= 1);
        layout->rowsPerImage = heightInBlocks;
    }
}

MaybeError ValidateLinearTextureData(const TextureDataLayout& layout,
                                     uint64_t byteSize,
                                     const TexelBlockInfo& blockInfo,
                                     const Extent3D& copyExtent) {
    DAWN_ASSERT(copyExtent.height % blockInfo.height == 0);
    uint32_t heightInBlocks = copyExtent.height / blockInfo.height;

    // TODO(dawn:563): Right now kCopyStrideUndefined will be formatted as a large value in the
    // validation message. Investigate ways to make it print as a more readable symbol.
    DAWN_INVALID_IF(
        copyExtent.depthOrArrayLayers > 1 && (layout.bytesPerRow == wgpu::kCopyStrideUndefined ||
                                              layout.rowsPerImage == wgpu::kCopyStrideUndefined),
        "Copy depth (%u) is > 1, but bytesPerRow (%u) or rowsPerImage (%u) are not specified.",
        copyExtent.depthOrArrayLayers, layout.bytesPerRow, layout.rowsPerImage);

    DAWN_INVALID_IF(heightInBlocks > 1 && layout.bytesPerRow == wgpu::kCopyStrideUndefined,
                    "HeightInBlocks (%u) is > 1, but bytesPerRow is not specified.",
                    heightInBlocks);

    // Validation for other members in layout:
    DAWN_ASSERT(copyExtent.width % blockInfo.width == 0);
    uint32_t widthInBlocks = copyExtent.width / blockInfo.width;
    DAWN_ASSERT(Safe32x32(widthInBlocks, blockInfo.byteSize) <=
                std::numeric_limits<uint32_t>::max());
    uint32_t bytesInLastRow = widthInBlocks * blockInfo.byteSize;

    // These != wgpu::kCopyStrideUndefined checks are technically redundant with the > checks,
    // but they should get optimized out.
    DAWN_INVALID_IF(
        layout.bytesPerRow != wgpu::kCopyStrideUndefined && bytesInLastRow > layout.bytesPerRow,
        "The byte size of each row (%u) is > bytesPerRow (%u).", bytesInLastRow,
        layout.bytesPerRow);

    DAWN_INVALID_IF(
        layout.rowsPerImage != wgpu::kCopyStrideUndefined && heightInBlocks > layout.rowsPerImage,
        "The height of each image in blocks (%u) is > rowsPerImage (%u).", heightInBlocks,
        layout.rowsPerImage);

    // We compute required bytes in copy after validating texel block alignments
    // because the divisibility conditions are necessary for the algorithm to be valid,
    // also the bytesPerRow bound is necessary to avoid overflows.
    uint64_t requiredBytesInCopy;
    DAWN_TRY_ASSIGN(
        requiredBytesInCopy,
        ComputeRequiredBytesInCopy(blockInfo, copyExtent, layout.bytesPerRow, layout.rowsPerImage));

    bool fitsInData =
        layout.offset <= byteSize && (requiredBytesInCopy <= (byteSize - layout.offset));
    DAWN_INVALID_IF(
        !fitsInData,
        "Required size for texture data layout (%u) exceeds the linear data size (%u) with "
        "offset (%u).",
        requiredBytesInCopy, byteSize, layout.offset);

    return {};
}

MaybeError ValidateImageCopyBuffer(DeviceBase const* device,
                                   const ImageCopyBuffer& imageCopyBuffer) {
    DAWN_TRY(device->ValidateObject(imageCopyBuffer.buffer));
    if (imageCopyBuffer.layout.bytesPerRow != wgpu::kCopyStrideUndefined) {
        DAWN_INVALID_IF(imageCopyBuffer.layout.bytesPerRow % kTextureBytesPerRowAlignment != 0,
                        "bytesPerRow (%u) is not a multiple of %u.",
                        imageCopyBuffer.layout.bytesPerRow, kTextureBytesPerRowAlignment);
    }

    return {};
}

MaybeError ValidateImageCopyTexture(DeviceBase const* device,
                                    const ImageCopyTexture& textureCopy,
                                    const Extent3D& copySize) {
    const TextureBase* texture = textureCopy.texture;
    DAWN_TRY(device->ValidateObject(texture));

    DAWN_INVALID_IF(textureCopy.mipLevel >= texture->GetNumMipLevels(),
                    "MipLevel (%u) is greater than the number of mip levels (%u) in %s.",
                    textureCopy.mipLevel, texture->GetNumMipLevels(), texture);

    DAWN_TRY(ValidateTextureAspect(textureCopy.aspect));

    const auto aspect = SelectFormatAspects(texture->GetFormat(), textureCopy.aspect);
    DAWN_INVALID_IF(aspect == Aspect::None,
                    "%s format (%s) does not have the selected aspect (%s).", texture,
                    texture->GetFormat().format, textureCopy.aspect);

    if (texture->GetSampleCount() > 1 || texture->GetFormat().HasDepthOrStencil()) {
        Extent3D subresourceSize =
            texture->GetMipLevelSingleSubresourcePhysicalSize(textureCopy.mipLevel, aspect);
        DAWN_ASSERT(texture->GetDimension() == wgpu::TextureDimension::e2D);
        DAWN_INVALID_IF(
            textureCopy.origin.x != 0 || textureCopy.origin.y != 0 ||
                subresourceSize.width != copySize.width ||
                subresourceSize.height != copySize.height,
            "Copy origin (%s) and size (%s) does not cover the entire subresource (origin: "
            "[x: 0, y: 0], size: %s) of %s. The entire subresource must be copied when the "
            "format (%s) is a depth/stencil format or the sample count (%u) is > 1.",
            &textureCopy.origin, &copySize, &subresourceSize, texture, texture->GetFormat().format,
            texture->GetSampleCount());
    }

    return {};
}

MaybeError ValidateTextureCopyRange(DeviceBase const* device,
                                    const ImageCopyTexture& textureCopy,
                                    const Extent3D& copySize) {
    const TextureBase* texture = textureCopy.texture;
    const Format& format = textureCopy.texture->GetFormat();
    const Aspect aspect = ConvertAspect(format, textureCopy.aspect);

    DAWN_ASSERT(!format.IsMultiPlanar() || HasOneBit(aspect));

    // Validation for the copy being in-bounds:
    Extent3D mipSize =
        texture->GetMipLevelSingleSubresourcePhysicalSize(textureCopy.mipLevel, aspect);
    // For 1D/2D textures, include the array layer as depth so it can be checked with other
    // dimensions.
    if (texture->GetDimension() != wgpu::TextureDimension::e3D) {
        mipSize.depthOrArrayLayers = texture->GetArrayLayers();
    }
    // All texture dimensions are in uint32_t so by doing checks in uint64_t we avoid
    // overflows.
    DAWN_INVALID_IF(
        static_cast<uint64_t>(textureCopy.origin.x) + static_cast<uint64_t>(copySize.width) >
                static_cast<uint64_t>(mipSize.width) ||
            static_cast<uint64_t>(textureCopy.origin.y) + static_cast<uint64_t>(copySize.height) >
                static_cast<uint64_t>(mipSize.height) ||
            static_cast<uint64_t>(textureCopy.origin.z) +
                    static_cast<uint64_t>(copySize.depthOrArrayLayers) >
                static_cast<uint64_t>(mipSize.depthOrArrayLayers),
        "Texture copy range (origin: %s, copySize: %s) touches outside of %s mip level %u "
        "size (%s).",
        &textureCopy.origin, &copySize, texture, textureCopy.mipLevel, &mipSize);

    // Validation for the texel block alignments:
    if (format.isCompressed) {
        const TexelBlockInfo& blockInfo = format.GetAspectInfo(textureCopy.aspect).block;
        DAWN_INVALID_IF(
            textureCopy.origin.x % blockInfo.width != 0,
            "Texture copy origin.x (%u) is not a multiple of compressed texture format block "
            "width (%u).",
            textureCopy.origin.x, blockInfo.width);
        DAWN_INVALID_IF(
            textureCopy.origin.y % blockInfo.height != 0,
            "Texture copy origin.y (%u) is not a multiple of compressed texture format block "
            "height (%u).",
            textureCopy.origin.y, blockInfo.height);
        DAWN_INVALID_IF(
            copySize.width % blockInfo.width != 0,
            "copySize.width (%u) is not a multiple of compressed texture format block width "
            "(%u).",
            copySize.width, blockInfo.width);
        DAWN_INVALID_IF(copySize.height % blockInfo.height != 0,
                        "copySize.height (%u) is not a multiple of compressed texture format block "
                        "height (%u).",
                        copySize.height, blockInfo.height);
    }

    return {};
}

// Always returns a single aspect (color, stencil, depth, or ith plane for multi-planar
// formats).
ResultOrError<Aspect> SingleAspectUsedByImageCopyTexture(const ImageCopyTexture& view) {
    const Format& format = view.texture->GetFormat();
    switch (view.aspect) {
        case wgpu::TextureAspect::All: {
            DAWN_INVALID_IF(
                !HasOneBit(format.aspects),
                "More than a single aspect (%s) is selected for multi-planar format (%s) in "
                "%s <-> linear data copy.",
                view.aspect, format.format, view.texture);

            Aspect single = format.aspects;
            return single;
        }
        case wgpu::TextureAspect::DepthOnly:
            DAWN_ASSERT(format.aspects & Aspect::Depth);
            return Aspect::Depth;
        case wgpu::TextureAspect::StencilOnly:
            DAWN_ASSERT(format.aspects & Aspect::Stencil);
            return Aspect::Stencil;
        case wgpu::TextureAspect::Plane0Only:
            return Aspect::Plane0;
        case wgpu::TextureAspect::Plane1Only:
            return Aspect::Plane1;
        case wgpu::TextureAspect::Plane2Only:
            return Aspect::Plane2;
        case wgpu::TextureAspect::Undefined:
            break;
    }
    DAWN_UNREACHABLE();
}

MaybeError ValidateLinearToDepthStencilCopyRestrictions(const ImageCopyTexture& dst) {
    Aspect aspectUsed;
    DAWN_TRY_ASSIGN(aspectUsed, SingleAspectUsedByImageCopyTexture(dst));

    const Format& format = dst.texture->GetFormat();
    switch (format.format) {
        case wgpu::TextureFormat::Depth16Unorm:
            return {};
        default:
            DAWN_INVALID_IF(aspectUsed == Aspect::Depth,
                            "Cannot copy into the depth aspect of %s with format %s.", dst.texture,
                            format.format);
            break;
    }

    return {};
}

MaybeError ValidateTextureToTextureCopyCommonRestrictions(DeviceBase const* device,
                                                          const ImageCopyTexture& src,
                                                          const ImageCopyTexture& dst,
                                                          const Extent3D& copySize) {
    const uint32_t srcSamples = src.texture->GetSampleCount();
    const uint32_t dstSamples = dst.texture->GetSampleCount();

    DAWN_INVALID_IF(
        srcSamples != dstSamples,
        "Source %s sample count (%u) and destination %s sample count (%u) does not match.",
        src.texture, srcSamples, dst.texture, dstSamples);

    DAWN_INVALID_IF(device->IsCompatibilityMode() && srcSamples != 1,
                    "Source %s and destination %s with sample count (%u) > 1 cannot be copied in "
                    "compatibility mode.",
                    src.texture, dst.texture, srcSamples);

    // Metal cannot select a single aspect for texture-to-texture copies.
    const Format& format = src.texture->GetFormat();
    DAWN_INVALID_IF(
        SelectFormatAspects(format, src.aspect) != format.aspects,
        "Source %s aspect (%s) doesn't select all the aspects of the source format (%s).",
        src.texture, src.aspect, format.format);

    DAWN_INVALID_IF(
        SelectFormatAspects(format, dst.aspect) != format.aspects,
        "Destination %s aspect (%s) doesn't select all the aspects of the destination format "
        "(%s).",
        dst.texture, dst.aspect, format.format);

    if (src.texture == dst.texture) {
        switch (src.texture->GetDimension()) {
            case wgpu::TextureDimension::Undefined:
                DAWN_UNREACHABLE();

            case wgpu::TextureDimension::e1D:
                DAWN_ASSERT(src.mipLevel == 0);
                return DAWN_VALIDATION_ERROR("Copy is from %s to itself.", src.texture);

            case wgpu::TextureDimension::e2D:
                DAWN_INVALID_IF(
                    src.mipLevel == dst.mipLevel &&
                        IsRangeOverlapped(src.origin.z, dst.origin.z, copySize.depthOrArrayLayers),
                    "Copy source and destination are overlapping layer ranges "
                    "([%u, %u) and [%u, %u)) of %s mip level %u",
                    src.origin.z, src.origin.z + copySize.depthOrArrayLayers, dst.origin.z,
                    dst.origin.z + copySize.depthOrArrayLayers, src.texture, src.mipLevel);
                break;

            case wgpu::TextureDimension::e3D:
                DAWN_INVALID_IF(src.mipLevel == dst.mipLevel,
                                "Copy is from %s mip level %u to itself.", src.texture,
                                src.mipLevel);
                break;
        }
    }

    return {};
}

MaybeError ValidateTextureToTextureCopyRestrictions(DeviceBase const* device,
                                                    const ImageCopyTexture& src,
                                                    const ImageCopyTexture& dst,
                                                    const Extent3D& copySize) {
    // Metal requires texture-to-texture copies happens between texture formats that equal to
    // each other or only have diff on srgb-ness.
    DAWN_INVALID_IF(!src.texture->GetFormat().CopyCompatibleWith(dst.texture->GetFormat()),
                    "Source %s format (%s) and destination %s format (%s) are not copy compatible.",
                    src.texture, src.texture->GetFormat().format, dst.texture,
                    dst.texture->GetFormat().format);

    return ValidateTextureToTextureCopyCommonRestrictions(device, src, dst, copySize);
}

MaybeError ValidateCanUseAs(const TextureBase* texture,
                            wgpu::TextureUsage usage,
                            UsageValidationMode mode) {
    DAWN_ASSERT(wgpu::HasZeroOrOneBits(usage));
    switch (mode) {
        case UsageValidationMode::Default:
            DAWN_INVALID_IF(!(texture->GetUsage() & usage), "%s usage (%s) doesn't include %s.",
                            texture, texture->GetUsage(), usage);
            break;
        case UsageValidationMode::Internal:
            DAWN_INVALID_IF(!(texture->GetInternalUsage() & usage),
                            "%s internal usage (%s) doesn't include %s.", texture,
                            texture->GetInternalUsage(), usage);
            break;
    }
    return {};
}

MaybeError ValidateCanUseAs(const BufferBase* buffer, wgpu::BufferUsage usage) {
    DAWN_ASSERT(wgpu::HasZeroOrOneBits(usage));
    DAWN_INVALID_IF(!(buffer->GetUsageExternalOnly() & usage), "%s usage (%s) doesn't include %s.",
                    buffer, buffer->GetUsageExternalOnly(), usage);
    return {};
}

namespace {
std::string TextureFormatsToString(const ColorAttachmentFormats& formats) {
    std::ostringstream ss;
    ss << "[ ";
    for (const Format* format : formats) {
        ss << absl::StrFormat("%s", format->format) << " ";
    }
    ss << "]";
    return ss.str();
}
}  // anonymous namespace

MaybeError ValidateColorAttachmentBytesPerSample(DeviceBase* device,
                                                 const ColorAttachmentFormats& formats) {
    uint32_t totalByteSize = 0;
    for (const Format* format : formats) {
        totalByteSize = Align(totalByteSize, format->renderTargetComponentAlignment);
        totalByteSize += format->renderTargetPixelByteCost;
    }
    uint32_t maxColorAttachmentBytesPerSample =
        device->GetLimits().v1.maxColorAttachmentBytesPerSample;
    DAWN_INVALID_IF(
        totalByteSize > maxColorAttachmentBytesPerSample,
        "Total color attachment bytes per sample (%u) exceeds maximum (%u) with formats (%s).",
        totalByteSize, maxColorAttachmentBytesPerSample, TextureFormatsToString(formats));

    return {};
}

MaybeError ValidatePLSInfo(
    const DeviceBase* device,
    uint64_t totalSize,
    ityp::span<size_t, StorageAttachmentInfoForValidation> storageAttachments) {
    DAWN_INVALID_IF(
        !(device->HasFeature(Feature::PixelLocalStorageCoherent) ||
          device->HasFeature(Feature::PixelLocalStorageNonCoherent)),
        "Pixel Local Storage feature used without either of the pixel-local-storage-coherent or "
        "pixel-local-storage-non-coherent features enabled.");

    // Validate totalPixelLocalStorageSize
    DAWN_INVALID_IF(totalSize % kPLSSlotByteSize != 0,
                    "totalPixelLocalStorageSize (%i) is not a multiple of %i.", totalSize,
                    kPLSSlotByteSize);
    DAWN_INVALID_IF(totalSize > kMaxPLSSize,
                    "totalPixelLocalStorageSize (%i) is larger than maxPixelLocalStorageSize (%i).",
                    totalSize, kMaxPLSSize);

    std::array<size_t, kMaxPLSSlots> indexForSlot;
    constexpr size_t kSlotNotSet = std::numeric_limits<size_t>::max();
    indexForSlot.fill(kSlotNotSet);
    for (size_t i = 0; i < storageAttachments.size(); i++) {
        const Format& format = device->GetValidInternalFormat(storageAttachments[i].format);
        DAWN_ASSERT(format.supportsStorageAttachment);

        // Validate the slot's offset.
        uint64_t offset = storageAttachments[i].offset;
        DAWN_INVALID_IF(offset % kPLSSlotByteSize != 0,
                        "storageAttachments[%i].offset (%i) is not a multiple of %i.", i, offset,
                        kPLSSlotByteSize);
        DAWN_INVALID_IF(
            offset > kMaxPLSSize,
            "storageAttachments[%i].offset (%i) is larger than maxPixelLocalStorageSize (%i).", i,
            offset, kMaxPLSSize);
        // This can't overflow because kMaxPLSSize + max texel byte size is way less than 2^32.
        DAWN_INVALID_IF(
            offset + format.GetAspectInfo(Aspect::Color).block.byteSize > totalSize,
            "storageAttachments[%i]'s footprint [%i, %i) does not fit in the total size (%i).", i,
            offset, format.GetAspectInfo(Aspect::Color).block.byteSize, totalSize);

        // Validate that there are no collisions, each storage attachment takes a single slot so
        // we don't need to loop over all slots for a storage attachment.
        DAWN_ASSERT(format.GetAspectInfo(Aspect::Color).block.byteSize == kPLSSlotByteSize);
        size_t slot = offset / kPLSSlotByteSize;
        DAWN_INVALID_IF(indexForSlot[slot] != kSlotNotSet,
                        "storageAttachments[%i] and storageAttachment[%i] conflict.", i,
                        indexForSlot[slot]);
        indexForSlot[slot] = i;
    }

    return {};
}

}  // namespace dawn::native
