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

#include "dawn/native/Texture.h"

#include <algorithm>

#include "dawn/common/Assert.h"
#include "dawn/common/Constants.h"
#include "dawn/common/Math.h"
#include "dawn/native/Adapter.h"
#include "dawn/native/ChainUtils_autogen.h"
#include "dawn/native/Device.h"
#include "dawn/native/EnumMaskIterator.h"
#include "dawn/native/ObjectType_autogen.h"
#include "dawn/native/PassResourceUsage.h"
#include "dawn/native/ValidationUtils_autogen.h"

namespace dawn::native {
    namespace {
        // WebGPU currently does not have texture format reinterpretation. If it does, the
        // code to check for it might go here.
        MaybeError ValidateTextureViewFormatCompatibility(const TextureBase* texture,
                                                          const TextureViewDescriptor* descriptor) {
            if (texture->GetFormat().format != descriptor->format) {
                if (descriptor->aspect != wgpu::TextureAspect::All &&
                    texture->GetFormat().GetAspectInfo(descriptor->aspect).format ==
                        descriptor->format) {
                    return {};
                }

                return DAWN_VALIDATION_ERROR(
                    "The format of texture view is not compatible to the original texture");
            }

            return {};
        }

        bool IsTextureViewDimensionCompatibleWithTextureDimension(
            wgpu::TextureViewDimension textureViewDimension,
            wgpu::TextureDimension textureDimension) {
            switch (textureViewDimension) {
                case wgpu::TextureViewDimension::e2D:
                case wgpu::TextureViewDimension::e2DArray:
                case wgpu::TextureViewDimension::Cube:
                case wgpu::TextureViewDimension::CubeArray:
                    return textureDimension == wgpu::TextureDimension::e2D;

                case wgpu::TextureViewDimension::e3D:
                    return textureDimension == wgpu::TextureDimension::e3D;

                case wgpu::TextureViewDimension::e1D:
                    return textureDimension == wgpu::TextureDimension::e1D;

                case wgpu::TextureViewDimension::Undefined:
                    UNREACHABLE();
            }
        }

        bool IsArrayLayerValidForTextureViewDimension(
            wgpu::TextureViewDimension textureViewDimension,
            uint32_t textureViewArrayLayer) {
            switch (textureViewDimension) {
                case wgpu::TextureViewDimension::e2D:
                case wgpu::TextureViewDimension::e3D:
                    return textureViewArrayLayer == 1u;
                case wgpu::TextureViewDimension::e2DArray:
                    return true;
                case wgpu::TextureViewDimension::Cube:
                    return textureViewArrayLayer == 6u;
                case wgpu::TextureViewDimension::CubeArray:
                    return textureViewArrayLayer % 6 == 0;
                case wgpu::TextureViewDimension::e1D:
                    return textureViewArrayLayer == 1u;

                case wgpu::TextureViewDimension::Undefined:
                    UNREACHABLE();
            }
        }

        MaybeError ValidateSampleCount(const TextureDescriptor* descriptor,
                                       wgpu::TextureUsage usage,
                                       const Format* format) {
            DAWN_INVALID_IF(!IsValidSampleCount(descriptor->sampleCount),
                            "The sample count (%u) of the texture is not supported.",
                            descriptor->sampleCount);

            if (descriptor->sampleCount > 1) {
                DAWN_INVALID_IF(descriptor->mipLevelCount > 1,
                                "The mip level count (%u) of a multisampled texture is not 1.",
                                descriptor->mipLevelCount);

                // Multisampled 1D and 3D textures are not supported in D3D12/Metal/Vulkan.
                // Multisampled 2D array texture is not supported because on Metal it requires the
                // version of macOS be greater than 10.14.
                DAWN_INVALID_IF(descriptor->dimension != wgpu::TextureDimension::e2D,
                                "The dimension (%s) of a multisampled texture is not 2D.",
                                descriptor->dimension);

                DAWN_INVALID_IF(descriptor->size.depthOrArrayLayers > 1,
                                "The depthOrArrayLayers (%u) of a multisampled texture is not 1.",
                                descriptor->size.depthOrArrayLayers);

                DAWN_INVALID_IF(!format->supportsMultisample,
                                "The texture format (%s) does not support multisampling.",
                                format->format);

                // Compressed formats are not renderable. They cannot support multisample.
                ASSERT(!format->isCompressed);

                DAWN_INVALID_IF(usage & wgpu::TextureUsage::StorageBinding,
                                "The sample count (%u) of a storage textures is not 1.",
                                descriptor->sampleCount);
            }

            return {};
        }

        MaybeError ValidateTextureViewDimensionCompatibility(
            const TextureBase* texture,
            const TextureViewDescriptor* descriptor) {
            DAWN_INVALID_IF(
                !IsArrayLayerValidForTextureViewDimension(descriptor->dimension,
                                                          descriptor->arrayLayerCount),
                "The dimension (%s) of the texture view is not compatible with the layer count "
                "(%u) of %s.",
                descriptor->dimension, descriptor->arrayLayerCount, texture);

            DAWN_INVALID_IF(
                !IsTextureViewDimensionCompatibleWithTextureDimension(descriptor->dimension,
                                                                      texture->GetDimension()),
                "The dimension (%s) of the texture view is not compatible with the dimension (%s) "
                "of %s.",
                descriptor->dimension, texture->GetDimension(), texture);

            switch (descriptor->dimension) {
                case wgpu::TextureViewDimension::Cube:
                case wgpu::TextureViewDimension::CubeArray:
                    DAWN_INVALID_IF(
                        texture->GetSize().width != texture->GetSize().height,
                        "A %s texture view is not compatible with %s because the texture's width "
                        "(%u) and height (%u) are not equal.",
                        descriptor->dimension, texture, texture->GetSize().width,
                        texture->GetSize().height);
                    break;

                case wgpu::TextureViewDimension::e1D:
                case wgpu::TextureViewDimension::e2D:
                case wgpu::TextureViewDimension::e2DArray:
                case wgpu::TextureViewDimension::e3D:
                    break;

                case wgpu::TextureViewDimension::Undefined:
                    UNREACHABLE();
            }

            return {};
        }

        MaybeError ValidateTextureSize(const DeviceBase* device,
                                       const TextureDescriptor* descriptor,
                                       const Format* format) {
            ASSERT(descriptor->size.width != 0 && descriptor->size.height != 0 &&
                   descriptor->size.depthOrArrayLayers != 0);
            const CombinedLimits& limits = device->GetLimits();
            Extent3D maxExtent;
            switch (descriptor->dimension) {
                case wgpu::TextureDimension::e1D:
                    maxExtent = {limits.v1.maxTextureDimension1D, 1, 1};
                    break;
                case wgpu::TextureDimension::e2D:
                    maxExtent = {limits.v1.maxTextureDimension2D, limits.v1.maxTextureDimension2D,
                                 limits.v1.maxTextureArrayLayers};
                    break;
                case wgpu::TextureDimension::e3D:
                    maxExtent = {limits.v1.maxTextureDimension3D, limits.v1.maxTextureDimension3D,
                                 limits.v1.maxTextureDimension3D};
                    break;
            }
            DAWN_INVALID_IF(descriptor->size.width > maxExtent.width ||
                                descriptor->size.height > maxExtent.height ||
                                descriptor->size.depthOrArrayLayers > maxExtent.depthOrArrayLayers,
                            "Texture size (%s) exceeded maximum texture size (%s).",
                            &descriptor->size, &maxExtent);

            switch (descriptor->dimension) {
                case wgpu::TextureDimension::e1D:
                    DAWN_INVALID_IF(
                        descriptor->mipLevelCount != 1,
                        "Texture mip level count (%u) is more than 1 when its dimension is %s.",
                        descriptor->mipLevelCount, wgpu::TextureDimension::e1D);
                    break;
                case wgpu::TextureDimension::e2D: {
                    uint32_t maxMippedDimension =
                        std::max(descriptor->size.width, descriptor->size.height);
                    DAWN_INVALID_IF(
                        Log2(maxMippedDimension) + 1 < descriptor->mipLevelCount,
                        "Texture mip level count (%u) exceeds the maximum (%u) for its size (%s).",
                        descriptor->mipLevelCount, Log2(maxMippedDimension) + 1, &descriptor->size);
                    break;
                }
                case wgpu::TextureDimension::e3D: {
                    uint32_t maxMippedDimension = std::max(
                        descriptor->size.width,
                        std::max(descriptor->size.height, descriptor->size.depthOrArrayLayers));
                    DAWN_INVALID_IF(
                        Log2(maxMippedDimension) + 1 < descriptor->mipLevelCount,
                        "Texture mip level count (%u) exceeds the maximum (%u) for its size (%s).",
                        descriptor->mipLevelCount, Log2(maxMippedDimension) + 1, &descriptor->size);
                    break;
                }
            }

            if (format->isCompressed) {
                const TexelBlockInfo& blockInfo =
                    format->GetAspectInfo(wgpu::TextureAspect::All).block;
                DAWN_INVALID_IF(
                    descriptor->size.width % blockInfo.width != 0 ||
                        descriptor->size.height % blockInfo.height != 0,
                    "The size (%s) of the texture is not a multiple of the block width (%u) and "
                    "height (%u) of the texture format (%s).",
                    &descriptor->size, blockInfo.width, blockInfo.height, format->format);
            }

            return {};
        }

        MaybeError ValidateTextureUsage(const TextureDescriptor* descriptor,
                                        wgpu::TextureUsage usage,
                                        const Format* format) {
            DAWN_TRY(dawn::native::ValidateTextureUsage(usage));

            DAWN_INVALID_IF(usage == wgpu::TextureUsage::None, "The texture usage must not be 0.");

            constexpr wgpu::TextureUsage kValidCompressedUsages =
                wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopySrc |
                wgpu::TextureUsage::CopyDst;
            DAWN_INVALID_IF(
                format->isCompressed && !IsSubset(usage, kValidCompressedUsages),
                "The texture usage (%s) is incompatible with the compressed texture format (%s).",
                usage, format->format);

            DAWN_INVALID_IF(
                !format->isRenderable && (usage & wgpu::TextureUsage::RenderAttachment),
                "The texture usage (%s) includes %s, which is incompatible with the non-renderable "
                "format (%s).",
                usage, wgpu::TextureUsage::RenderAttachment, format->format);

            DAWN_INVALID_IF(
                !format->supportsStorageUsage && (usage & wgpu::TextureUsage::StorageBinding),
                "The texture usage (%s) includes %s, which is incompatible with the format (%s).",
                usage, wgpu::TextureUsage::StorageBinding, format->format);

            // Only allows simple readonly texture usages.
            constexpr wgpu::TextureUsage kValidMultiPlanarUsages =
                wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopySrc;
            DAWN_INVALID_IF(
                format->IsMultiPlanar() && !IsSubset(usage, kValidMultiPlanarUsages),
                "The texture usage (%s) is incompatible with the multi-planar format (%s).", usage,
                format->format);

            return {};
        }

    }  // anonymous namespace

    MaybeError ValidateTextureDescriptor(const DeviceBase* device,
                                         const TextureDescriptor* descriptor) {
        DAWN_TRY(ValidateSingleSType(descriptor->nextInChain,
                                     wgpu::SType::DawnTextureInternalUsageDescriptor));

        const DawnTextureInternalUsageDescriptor* internalUsageDesc = nullptr;
        FindInChain(descriptor->nextInChain, &internalUsageDesc);

        DAWN_INVALID_IF(
            internalUsageDesc != nullptr && !device->IsFeatureEnabled(Feature::DawnInternalUsages),
            "The dawn-internal-usages feature is not enabled");

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

        wgpu::TextureUsage usage = descriptor->usage;
        if (internalUsageDesc != nullptr) {
            usage |= internalUsageDesc->internalUsage;
        }

        DAWN_TRY(ValidateTextureUsage(descriptor, usage, format));
        DAWN_TRY(ValidateTextureDimension(descriptor->dimension));
        DAWN_TRY(ValidateSampleCount(descriptor, usage, format));

        DAWN_INVALID_IF(descriptor->size.width == 0 || descriptor->size.height == 0 ||
                            descriptor->size.depthOrArrayLayers == 0 ||
                            descriptor->mipLevelCount == 0,
                        "The texture size (%s) or mipLevelCount (%u) is empty.", &descriptor->size,
                        descriptor->mipLevelCount);

        DAWN_INVALID_IF(
            descriptor->dimension != wgpu::TextureDimension::e2D && format->isCompressed,
            "The dimension (%s) of a texture with a compressed format (%s) is not 2D.",
            descriptor->dimension, format->format);

        // Depth/stencil formats are valid for 2D textures only. Metal has this limit. And D3D12
        // doesn't support depth/stencil formats on 3D textures.
        DAWN_INVALID_IF(
            descriptor->dimension != wgpu::TextureDimension::e2D &&
                (format->aspects & (Aspect::Depth | Aspect::Stencil)) != 0,
            "The dimension (%s) of a texture with a depth/stencil format (%s) is not 2D.",
            descriptor->dimension, format->format);

        DAWN_TRY(ValidateTextureSize(device, descriptor, format));

        // TODO(crbug.com/dawn/838): Implement a workaround for this issue.
        // Readbacks from the non-zero mip of a stencil texture may contain garbage data.
        DAWN_INVALID_IF(
            device->IsToggleEnabled(Toggle::DisallowUnsafeAPIs) && format->HasStencil() &&
                descriptor->mipLevelCount > 1 &&
                device->GetAdapter()->GetBackendType() == wgpu::BackendType::Metal,
            "https://crbug.com/dawn/838: Stencil textures with more than one mip level are "
            "disabled on Metal.");

        DAWN_INVALID_IF(
            device->IsToggleEnabled(Toggle::DisableR8RG8Mipmaps) && descriptor->mipLevelCount > 1 &&
                (descriptor->format == wgpu::TextureFormat::R8Unorm ||
                 descriptor->format == wgpu::TextureFormat::RG8Unorm),
            "https://crbug.com/dawn/1071: r8unorm and rg8unorm textures with more than one mip "
            "level are disabled on Metal.");

        return {};
    }

    MaybeError ValidateTextureViewDescriptor(const DeviceBase* device,
                                             const TextureBase* texture,
                                             const TextureViewDescriptor* descriptor) {
        DAWN_INVALID_IF(descriptor->nextInChain != nullptr, "nextInChain must be nullptr.");

        // Parent texture should have been already validated.
        ASSERT(texture);
        ASSERT(!texture->IsError());

        DAWN_TRY(ValidateTextureViewDimension(descriptor->dimension));
        DAWN_TRY(ValidateTextureFormat(descriptor->format));
        DAWN_TRY(ValidateTextureAspect(descriptor->aspect));

        DAWN_INVALID_IF(
            SelectFormatAspects(texture->GetFormat(), descriptor->aspect) == Aspect::None,
            "Texture format (%s) does not have the texture view's selected aspect (%s).",
            texture->GetFormat().format, descriptor->aspect);

        DAWN_INVALID_IF(descriptor->arrayLayerCount == 0 || descriptor->mipLevelCount == 0,
                        "The texture view's arrayLayerCount (%u) or mipLevelCount (%u) is zero.",
                        descriptor->arrayLayerCount, descriptor->mipLevelCount);

        DAWN_INVALID_IF(
            uint64_t(descriptor->baseArrayLayer) + uint64_t(descriptor->arrayLayerCount) >
                uint64_t(texture->GetArrayLayers()),
            "Texture view array layer range (baseArrayLayer: %u, arrayLayerCount: %u) exceeds the "
            "texture's array layer count (%u).",
            descriptor->baseArrayLayer, descriptor->arrayLayerCount, texture->GetArrayLayers());

        DAWN_INVALID_IF(
            uint64_t(descriptor->baseMipLevel) + uint64_t(descriptor->mipLevelCount) >
                uint64_t(texture->GetNumMipLevels()),
            "Texture view mip level range (baseMipLevel: %u, mipLevelCount: %u) exceeds the "
            "texture's mip level count (%u).",
            descriptor->baseMipLevel, descriptor->mipLevelCount, texture->GetNumMipLevels());

        DAWN_TRY(ValidateTextureViewFormatCompatibility(texture, descriptor));
        DAWN_TRY(ValidateTextureViewDimensionCompatibility(texture, descriptor));

        return {};
    }

    TextureViewDescriptor GetTextureViewDescriptorWithDefaults(
        const TextureBase* texture,
        const TextureViewDescriptor* descriptor) {
        ASSERT(texture);

        TextureViewDescriptor desc = {};
        if (descriptor) {
            desc = *descriptor;
        }

        // The default value for the view dimension depends on the texture's dimension with a
        // special case for 2DArray being chosen automatically if arrayLayerCount is unspecified.
        if (desc.dimension == wgpu::TextureViewDimension::Undefined) {
            switch (texture->GetDimension()) {
                case wgpu::TextureDimension::e1D:
                    desc.dimension = wgpu::TextureViewDimension::e1D;
                    break;

                case wgpu::TextureDimension::e2D:
                    desc.dimension = wgpu::TextureViewDimension::e2D;
                    break;

                case wgpu::TextureDimension::e3D:
                    desc.dimension = wgpu::TextureViewDimension::e3D;
                    break;
            }
        }

        if (desc.format == wgpu::TextureFormat::Undefined) {
            // TODO(dawn:682): Use GetAspectInfo(aspect).
            desc.format = texture->GetFormat().format;
        }
        if (desc.arrayLayerCount == wgpu::kArrayLayerCountUndefined) {
            switch (desc.dimension) {
                case wgpu::TextureViewDimension::e1D:
                case wgpu::TextureViewDimension::e2D:
                case wgpu::TextureViewDimension::e3D:
                    desc.arrayLayerCount = 1;
                    break;
                case wgpu::TextureViewDimension::Cube:
                    desc.arrayLayerCount = 6;
                    break;
                case wgpu::TextureViewDimension::e2DArray:
                case wgpu::TextureViewDimension::CubeArray:
                    desc.arrayLayerCount = texture->GetArrayLayers() - desc.baseArrayLayer;
                    break;
                default:
                    // We don't put UNREACHABLE() here because we validate enums only after this
                    // function sets default values. Otherwise, the UNREACHABLE() will be hit.
                    break;
            }
        }

        if (desc.mipLevelCount == wgpu::kMipLevelCountUndefined) {
            desc.mipLevelCount = texture->GetNumMipLevels() - desc.baseMipLevel;
        }
        return desc;
    }

    // WebGPU only supports sample counts of 1 and 4. We could expand to more based on
    // platform support, but it would probably be a feature.
    bool IsValidSampleCount(uint32_t sampleCount) {
        switch (sampleCount) {
            case 1:
            case 4:
                return true;

            default:
                return false;
        }
    }

    // TextureBase

    TextureBase::TextureBase(DeviceBase* device,
                             const TextureDescriptor* descriptor,
                             TextureState state)
        : ApiObjectBase(device, descriptor->label),
          mDimension(descriptor->dimension),
          mFormat(device->GetValidInternalFormat(descriptor->format)),
          mSize(descriptor->size),
          mMipLevelCount(descriptor->mipLevelCount),
          mSampleCount(descriptor->sampleCount),
          mUsage(descriptor->usage),
          mInternalUsage(mUsage),
          mState(state) {
        uint32_t subresourceCount =
            mMipLevelCount * GetArrayLayers() * GetAspectCount(mFormat.aspects);
        mIsSubresourceContentInitializedAtIndex = std::vector<bool>(subresourceCount, false);

        const DawnTextureInternalUsageDescriptor* internalUsageDesc = nullptr;
        FindInChain(descriptor->nextInChain, &internalUsageDesc);
        if (internalUsageDesc != nullptr) {
            mInternalUsage |= internalUsageDesc->internalUsage;
        }
        TrackInDevice();
    }

    static Format kUnusedFormat;

    TextureBase::TextureBase(DeviceBase* device, TextureState state)
        : ApiObjectBase(device, kLabelNotImplemented), mFormat(kUnusedFormat), mState(state) {
        TrackInDevice();
    }

    TextureBase::TextureBase(DeviceBase* device, ObjectBase::ErrorTag tag)
        : ApiObjectBase(device, tag), mFormat(kUnusedFormat) {
    }

    void TextureBase::DestroyImpl() {
        mState = TextureState::Destroyed;
    }

    // static
    TextureBase* TextureBase::MakeError(DeviceBase* device) {
        return new TextureBase(device, ObjectBase::kError);
    }

    ObjectType TextureBase::GetType() const {
        return ObjectType::Texture;
    }

    wgpu::TextureDimension TextureBase::GetDimension() const {
        ASSERT(!IsError());
        return mDimension;
    }

    const Format& TextureBase::GetFormat() const {
        ASSERT(!IsError());
        return mFormat;
    }
    const Extent3D& TextureBase::GetSize() const {
        ASSERT(!IsError());
        return mSize;
    }
    uint32_t TextureBase::GetWidth() const {
        ASSERT(!IsError());
        return mSize.width;
    }
    uint32_t TextureBase::GetHeight() const {
        ASSERT(!IsError());
        return mSize.height;
    }
    uint32_t TextureBase::GetDepth() const {
        ASSERT(!IsError());
        ASSERT(mDimension == wgpu::TextureDimension::e3D);
        return mSize.depthOrArrayLayers;
    }
    uint32_t TextureBase::GetArrayLayers() const {
        ASSERT(!IsError());
        if (mDimension == wgpu::TextureDimension::e3D) {
            return 1;
        }
        return mSize.depthOrArrayLayers;
    }
    uint32_t TextureBase::GetNumMipLevels() const {
        ASSERT(!IsError());
        return mMipLevelCount;
    }
    SubresourceRange TextureBase::GetAllSubresources() const {
        ASSERT(!IsError());
        return {mFormat.aspects, {0, GetArrayLayers()}, {0, mMipLevelCount}};
    }
    uint32_t TextureBase::GetSampleCount() const {
        ASSERT(!IsError());
        return mSampleCount;
    }
    uint32_t TextureBase::GetSubresourceCount() const {
        ASSERT(!IsError());
        return static_cast<uint32_t>(mIsSubresourceContentInitializedAtIndex.size());
    }
    wgpu::TextureUsage TextureBase::GetUsage() const {
        ASSERT(!IsError());
        return mUsage;
    }
    wgpu::TextureUsage TextureBase::GetInternalUsage() const {
        ASSERT(!IsError());
        return mInternalUsage;
    }

    TextureBase::TextureState TextureBase::GetTextureState() const {
        ASSERT(!IsError());
        return mState;
    }

    uint32_t TextureBase::GetSubresourceIndex(uint32_t mipLevel,
                                              uint32_t arraySlice,
                                              Aspect aspect) const {
        ASSERT(HasOneBit(aspect));
        return mipLevel +
               GetNumMipLevels() * (arraySlice + GetArrayLayers() * GetAspectIndex(aspect));
    }

    bool TextureBase::IsSubresourceContentInitialized(const SubresourceRange& range) const {
        ASSERT(!IsError());
        for (Aspect aspect : IterateEnumMask(range.aspects)) {
            for (uint32_t arrayLayer = range.baseArrayLayer;
                 arrayLayer < range.baseArrayLayer + range.layerCount; ++arrayLayer) {
                for (uint32_t mipLevel = range.baseMipLevel;
                     mipLevel < range.baseMipLevel + range.levelCount; ++mipLevel) {
                    uint32_t subresourceIndex = GetSubresourceIndex(mipLevel, arrayLayer, aspect);
                    ASSERT(subresourceIndex < mIsSubresourceContentInitializedAtIndex.size());
                    if (!mIsSubresourceContentInitializedAtIndex[subresourceIndex]) {
                        return false;
                    }
                }
            }
        }
        return true;
    }

    void TextureBase::SetIsSubresourceContentInitialized(bool isInitialized,
                                                         const SubresourceRange& range) {
        ASSERT(!IsError());
        for (Aspect aspect : IterateEnumMask(range.aspects)) {
            for (uint32_t arrayLayer = range.baseArrayLayer;
                 arrayLayer < range.baseArrayLayer + range.layerCount; ++arrayLayer) {
                for (uint32_t mipLevel = range.baseMipLevel;
                     mipLevel < range.baseMipLevel + range.levelCount; ++mipLevel) {
                    uint32_t subresourceIndex = GetSubresourceIndex(mipLevel, arrayLayer, aspect);
                    ASSERT(subresourceIndex < mIsSubresourceContentInitializedAtIndex.size());
                    mIsSubresourceContentInitializedAtIndex[subresourceIndex] = isInitialized;
                }
            }
        }
    }

    MaybeError TextureBase::ValidateCanUseInSubmitNow() const {
        ASSERT(!IsError());
        DAWN_INVALID_IF(mState == TextureState::Destroyed, "Destroyed texture %s used in a submit.",
                        this);
        return {};
    }

    bool TextureBase::IsMultisampledTexture() const {
        ASSERT(!IsError());
        return mSampleCount > 1;
    }

    Extent3D TextureBase::GetMipLevelVirtualSize(uint32_t level) const {
        Extent3D extent = {std::max(mSize.width >> level, 1u), 1u, 1u};
        if (mDimension == wgpu::TextureDimension::e1D) {
            return extent;
        }

        extent.height = std::max(mSize.height >> level, 1u);
        if (mDimension == wgpu::TextureDimension::e2D) {
            return extent;
        }

        extent.depthOrArrayLayers = std::max(mSize.depthOrArrayLayers >> level, 1u);
        return extent;
    }

    Extent3D TextureBase::GetMipLevelPhysicalSize(uint32_t level) const {
        Extent3D extent = GetMipLevelVirtualSize(level);

        // Compressed Textures will have paddings if their width or height is not a multiple of
        // 4 at non-zero mipmap levels.
        if (mFormat.isCompressed && level != 0) {
            // If |level| is non-zero, then each dimension of |extent| is at most half of
            // the max texture dimension. Computations here which add the block width/height
            // to the extent cannot overflow.
            const TexelBlockInfo& blockInfo = mFormat.GetAspectInfo(wgpu::TextureAspect::All).block;
            extent.width = (extent.width + blockInfo.width - 1) / blockInfo.width * blockInfo.width;
            extent.height =
                (extent.height + blockInfo.height - 1) / blockInfo.height * blockInfo.height;
        }

        return extent;
    }

    Extent3D TextureBase::ClampToMipLevelVirtualSize(uint32_t level,
                                                     const Origin3D& origin,
                                                     const Extent3D& extent) const {
        const Extent3D virtualSizeAtLevel = GetMipLevelVirtualSize(level);
        ASSERT(origin.x <= virtualSizeAtLevel.width);
        ASSERT(origin.y <= virtualSizeAtLevel.height);
        uint32_t clampedCopyExtentWidth = (extent.width > virtualSizeAtLevel.width - origin.x)
                                              ? (virtualSizeAtLevel.width - origin.x)
                                              : extent.width;
        uint32_t clampedCopyExtentHeight = (extent.height > virtualSizeAtLevel.height - origin.y)
                                               ? (virtualSizeAtLevel.height - origin.y)
                                               : extent.height;
        return {clampedCopyExtentWidth, clampedCopyExtentHeight, extent.depthOrArrayLayers};
    }

    TextureViewBase* TextureBase::APICreateView(const TextureViewDescriptor* descriptor) {
        DeviceBase* device = GetDevice();

        Ref<TextureViewBase> result;
        if (device->ConsumedError(device->CreateTextureView(this, descriptor), &result,
                                  "calling %s.CreateView(%s).", this, descriptor)) {
            return TextureViewBase::MakeError(device);
        }
        return result.Detach();
    }

    void TextureBase::APIDestroy() {
        if (GetDevice()->ConsumedError(ValidateDestroy(), "calling %s.Destroy().", this)) {
            return;
        }
        ASSERT(!IsError());
        Destroy();
    }

    MaybeError TextureBase::ValidateDestroy() const {
        DAWN_TRY(GetDevice()->ValidateObject(this));
        return {};
    }

    // TextureViewBase

    TextureViewBase::TextureViewBase(TextureBase* texture, const TextureViewDescriptor* descriptor)
        : ApiObjectBase(texture->GetDevice(), descriptor->label),
          mTexture(texture),
          mFormat(GetDevice()->GetValidInternalFormat(descriptor->format)),
          mDimension(descriptor->dimension),
          mRange({ConvertViewAspect(mFormat, descriptor->aspect),
                  {descriptor->baseArrayLayer, descriptor->arrayLayerCount},
                  {descriptor->baseMipLevel, descriptor->mipLevelCount}}) {
        TrackInDevice();
    }

    TextureViewBase::TextureViewBase(TextureBase* texture)
        : ApiObjectBase(texture->GetDevice(), kLabelNotImplemented),
          mTexture(texture),
          mFormat(kUnusedFormat) {
        TrackInDevice();
    }

    TextureViewBase::TextureViewBase(DeviceBase* device, ObjectBase::ErrorTag tag)
        : ApiObjectBase(device, tag), mFormat(kUnusedFormat) {
    }

    void TextureViewBase::DestroyImpl() {
    }

    // static
    TextureViewBase* TextureViewBase::MakeError(DeviceBase* device) {
        return new TextureViewBase(device, ObjectBase::kError);
    }

    ObjectType TextureViewBase::GetType() const {
        return ObjectType::TextureView;
    }

    const TextureBase* TextureViewBase::GetTexture() const {
        ASSERT(!IsError());
        return mTexture.Get();
    }

    TextureBase* TextureViewBase::GetTexture() {
        ASSERT(!IsError());
        return mTexture.Get();
    }

    Aspect TextureViewBase::GetAspects() const {
        ASSERT(!IsError());
        return mRange.aspects;
    }

    const Format& TextureViewBase::GetFormat() const {
        ASSERT(!IsError());
        return mFormat;
    }

    wgpu::TextureViewDimension TextureViewBase::GetDimension() const {
        ASSERT(!IsError());
        return mDimension;
    }

    uint32_t TextureViewBase::GetBaseMipLevel() const {
        ASSERT(!IsError());
        return mRange.baseMipLevel;
    }

    uint32_t TextureViewBase::GetLevelCount() const {
        ASSERT(!IsError());
        return mRange.levelCount;
    }

    uint32_t TextureViewBase::GetBaseArrayLayer() const {
        ASSERT(!IsError());
        return mRange.baseArrayLayer;
    }

    uint32_t TextureViewBase::GetLayerCount() const {
        ASSERT(!IsError());
        return mRange.layerCount;
    }

    const SubresourceRange& TextureViewBase::GetSubresourceRange() const {
        ASSERT(!IsError());
        return mRange;
    }

}  // namespace dawn::native
