// Copyright 2018 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/vulkan/TextureVk.h"

#include <iostream>
#include <utility>

#include "dawn/native/VulkanBackend.h"
#include "src/dawn/common/DynamicLib.h"
#include "src/dawn/common/Math.h"
#include "src/dawn/native/ChainUtils.h"
#include "src/dawn/native/DynamicUploader.h"
#include "src/dawn/native/EnumMaskIterator.h"
#include "src/dawn/native/Error.h"
#include "src/dawn/native/utils/RenderDoc.h"
#include "src/dawn/native/vulkan/BufferVk.h"
#include "src/dawn/native/vulkan/CommandBufferVk.h"
#include "src/dawn/native/vulkan/CommandRecordingContextVk.h"
#include "src/dawn/native/vulkan/DeviceVk.h"
#include "src/dawn/native/vulkan/FencedDeleter.h"
#include "src/dawn/native/vulkan/PhysicalDeviceVk.h"
#include "src/dawn/native/vulkan/QueueVk.h"
#include "src/dawn/native/vulkan/ResourceHeapVk.h"
#include "src/dawn/native/vulkan/ResourceMemoryAllocatorVk.h"
#include "src/dawn/native/vulkan/SamplerVk.h"
#include "src/dawn/native/vulkan/SharedFenceVk.h"
#include "src/dawn/native/vulkan/UtilsVulkan.h"
#include "src/dawn/native/vulkan/VulkanError.h"
#include "src/utils/assert.h"
#include "src/utils/compiler.h"
#include "src/utils/numeric.h"

namespace dawn::native::vulkan {

namespace {
// Converts an Dawn texture dimension to a Vulkan image view type.
// Contrary to image types, image view types include arrayness and cubemapness
VkImageViewType VulkanImageViewType(wgpu::TextureViewDimension dimension) {
    switch (dimension) {
        case wgpu::TextureViewDimension::e1D:
            return VK_IMAGE_VIEW_TYPE_1D;
        case wgpu::TextureViewDimension::e2D:
            return VK_IMAGE_VIEW_TYPE_2D;
        case wgpu::TextureViewDimension::e2DArray:
            return VK_IMAGE_VIEW_TYPE_2D_ARRAY;
        case wgpu::TextureViewDimension::Cube:
            return VK_IMAGE_VIEW_TYPE_CUBE;
        case wgpu::TextureViewDimension::CubeArray:
            return VK_IMAGE_VIEW_TYPE_CUBE_ARRAY;
        case wgpu::TextureViewDimension::e3D:
            return VK_IMAGE_VIEW_TYPE_3D;

        case wgpu::TextureViewDimension::Undefined:
            break;
    }
    DAWN_UNREACHABLE();
}

// Reserved texture usages to represent mixed read-only/writable depth-stencil texture usages
// when combining the planes of depth-stencil textures. They can be combined with other in-pass
// readonly usages like wgpu::TextureUsage::TextureBinding.
// TODO(dawn:2172): Consider making a bespoke enum instead of hackily extending TextureUsage.
constexpr wgpu::TextureUsage kDepthReadOnlyStencilWritableAttachment =
    kReservedTextureUsage | static_cast<wgpu::TextureUsage>(1 << 30);
constexpr wgpu::TextureUsage kDepthWritableStencilReadOnlyAttachment =
    kReservedTextureUsage | static_cast<wgpu::TextureUsage>(1 << 29);

// Merge two usages for depth and stencil into a single combined usage that uses the reserved
// texture usages above. This is used to handle combining Aspect::Depth and Aspect::Stencil into a
// single Aspect::CombinedDepthStencil.
wgpu::TextureUsage MergeDepthStencilUsage(wgpu::TextureUsage depth, wgpu::TextureUsage stencil) {
    // Aspects that are RenderAttachment cannot be anything else at the same time. This lets us
    // check if we are in one of the RenderAttachment + (ReadOnlyAttachment|readonly usage) cases
    // and know only the aspect with the readonly attachment might contain extra usages like
    // TextureBinding.
    DAWN_ASSERT(depth == wgpu::TextureUsage::RenderAttachment ||
                IsSubset(depth, ~wgpu::TextureUsage::RenderAttachment));
    DAWN_ASSERT(stencil == wgpu::TextureUsage::RenderAttachment ||
                IsSubset(stencil, ~wgpu::TextureUsage::RenderAttachment));

    if (depth == wgpu::TextureUsage::RenderAttachment && stencil & kReadOnlyRenderAttachment) {
        return kDepthWritableStencilReadOnlyAttachment | (stencil & ~kReadOnlyRenderAttachment);
    } else if (depth & kReadOnlyRenderAttachment &&
               stencil == wgpu::TextureUsage::RenderAttachment) {
        return kDepthReadOnlyStencilWritableAttachment | (depth & ~kReadOnlyRenderAttachment);
    } else {
        // Not one of the reserved usage special cases, we can just combine the aspect's usage the
        // simple way!
        return depth | stencil;
    }
}

// Computes which vulkan access type could be required for the given Dawn usage.
// TODO(crbug.com/dawn/269): We shouldn't need any access usages for srcAccessMask when
// the previous usage is readonly because an execution dependency is sufficient.
VkAccessFlags VulkanAccessFlags(wgpu::TextureUsage usage, const Format& format) {
    if (usage & kReservedTextureUsage) {
        // Handle the special readonly usages for mixed depth-stencil.
        DAWN_ASSERT(IsSubset(kDepthReadOnlyStencilWritableAttachment, usage) ||
                    IsSubset(kDepthWritableStencilReadOnlyAttachment, usage));

        // Add any additional access flags for the non-attachment part of the usage.
        const wgpu::TextureUsage nonAttachmentUsages =
            usage &
            ~(kDepthReadOnlyStencilWritableAttachment | kDepthWritableStencilReadOnlyAttachment);
        return VulkanAccessFlags(nonAttachmentUsages, format) |
               VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
               VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
    }

    VkAccessFlags flags = 0;
    if (usage & wgpu::TextureUsage::CopySrc) {
        flags |= VK_ACCESS_TRANSFER_READ_BIT;
    }
    if (usage & wgpu::TextureUsage::CopyDst) {
        flags |= VK_ACCESS_TRANSFER_WRITE_BIT;
    }
    if (usage & (wgpu::TextureUsage::TextureBinding | kReadOnlyStorageTexture)) {
        flags |= VK_ACCESS_SHADER_READ_BIT;
    }
    if (usage & kWriteOnlyStorageTexture) {
        flags |= VK_ACCESS_SHADER_WRITE_BIT;
    }
    if (usage & wgpu::TextureUsage::StorageBinding) {
        flags |= VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT;
    }
    if (usage & wgpu::TextureUsage::RenderAttachment) {
        if (format.HasDepthOrStencil()) {
            flags |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
                     VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
        } else {
            flags |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
        }
    }
    if (usage & kReadOnlyRenderAttachment) {
        flags |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
    }

    if (usage & kResolveAttachmentLoadingUsage) {
        // - The texture will be used as input attachment in the first subpass and loaded with
        // VK_ATTACHMENT_LOAD_OP_LOAD. This requires VK_ACCESS_COLOR_ATTACHMENT_READ_BIT access.
        // - It will also be read as subpass input in fragment shader. This requires
        // VK_ACCESS_INPUT_ATTACHMENT_READ_BIT.
        flags |= VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
    }

    if (usage & kPresentAcquireTextureUsage) {
        // The present acquire usage is only used internally by the swapchain and is never used in
        // combination with other usages.
        DAWN_ASSERT(usage == kPresentAcquireTextureUsage);
        // The Vulkan spec has the following note:
        //
        //   When the presentable image will be accessed by some stage S, the recommended idiom
        //   for ensuring correct synchronization is:
        //
        //   The VkSubmitInfo used to submit the image layout transition for execution includes
        //   vkAcquireNextImageKHR::semaphore in its pWaitSemaphores member, with the
        //   corresponding element of pWaitDstStageMask including S.
        //
        //   The synchronization command that performs any necessary image layout transition
        //   includes S in both the srcStageMask and dstStageMask.
        //
        // There is no mention of an access flag because there is no access flag associated with
        // the presentation engine, so we leave it to 0.
        flags |= 0;
    }
    if (usage & kPresentReleaseTextureUsage) {
        // The present release usage is only used internally by the swapchain and is never used in
        // combination with other usages.
        DAWN_ASSERT(usage == kPresentReleaseTextureUsage);
        // The Vulkan spec has the following note:
        //
        //   When transitioning the image to VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR or
        //   VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, there is no need to delay subsequent
        //   processing, or perform any visibility operations (as vkQueuePresentKHR performs
        //   automatic visibility operations). To achieve this, the dstAccessMask member of
        //   the VkImageMemoryBarrier should be set to 0, and the dstStageMask parameter
        //   should be set to VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT.
        //
        // So on the transition to Present we don't need an access flag. The other
        // direction doesn't matter because swapchain textures always start a new frame
        // as uninitialized.
        flags |= 0;
    }

    return flags;
}

// Computes which Vulkan pipeline stage can access a texture in the given Dawn usage
VkPipelineStageFlags VulkanPipelineStage(wgpu::TextureUsage usage,
                                         wgpu::ShaderStage shaderStage,
                                         const Format& format) {
    if (usage & kReservedTextureUsage) {
        // Handle the special readonly usages for mixed depth-stencil.
        DAWN_ASSERT(IsSubset(kDepthReadOnlyStencilWritableAttachment, usage) ||
                    IsSubset(kDepthWritableStencilReadOnlyAttachment, usage));

        // Convert all the reserved attachment usages into just RenderAttachment.
        const wgpu::TextureUsage nonAttachmentUsages =
            usage &
            ~(kDepthReadOnlyStencilWritableAttachment | kDepthWritableStencilReadOnlyAttachment);
        return VulkanPipelineStage(nonAttachmentUsages | wgpu::TextureUsage::RenderAttachment,
                                   shaderStage, format);
    }

    VkPipelineStageFlags flags = 0;

    if (usage == wgpu::TextureUsage::None) {
        // This only happens when a texture is initially created (and for srcAccessMask) in
        // which case there is no need to wait on anything to stop accessing this texture.
        return VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
    }
    if (usage & (wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst)) {
        flags |= VK_PIPELINE_STAGE_TRANSFER_BIT;
    }
    if (usage & kShaderTextureUsages) {
        if (shaderStage & wgpu::ShaderStage::Vertex) {
            flags |= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
        }
        if (shaderStage & wgpu::ShaderStage::Fragment) {
            flags |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
        }
        if (shaderStage & wgpu::ShaderStage::Compute) {
            flags |= VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
        }
    }
    if (usage & kResolveAttachmentLoadingUsage) {
        // - The texture will be used as input attachment in the first subpass and loaded with
        // VK_ATTACHMENT_LOAD_OP_LOAD. This happens at VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT
        // stage.
        // - It will also be read as subpass input in fragment shader.
        flags |=
            VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
    }
    if (usage & (wgpu::TextureUsage::RenderAttachment | kReadOnlyRenderAttachment)) {
        if (format.HasDepthOrStencil()) {
            flags |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT |
                     VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
        } else {
            flags |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
        }
    }

    if (usage & kPresentAcquireTextureUsage) {
        // The present acquire usage is only used internally by the swapchain and is never used in
        // combination with other usages.
        DAWN_ASSERT(usage == kPresentAcquireTextureUsage);
        // The vkAcquireNextImageKHR method is a read operation in Vulkan which completes
        // before the semaphore/fence out parameters are signaled. This means that future uses
        // of the texture must performs a memory barriers that synchronizes with that
        // semaphore/barrier. Dawn uses the ALL_COMMANDS_BIT stage for the semaphore, however
        // such a semaphore doesn't synchronize with a subsequent BOTTOM_OF_PIPE or NONE
        // srcStage vkPipelineBarrier because there are no common stages. Instead we also use
        // VK_PIPELINE_STAGE_ALL_COMMANDS_BIT for srcStage for presentable images, ensuring
        // correct ordering. This explains the idiom noted in the Vulkan spec:
        //
        //   When the presentable image will be accessed by some stage S, the recommended idiom
        //   for ensuring correct synchronization is:
        //
        //   The VkSubmitInfo used to submit the image layout transition for execution includes
        //   vkAcquireNextImageKHR::semaphore in its pWaitSemaphores member, with the
        //   corresponding element of pWaitDstStageMask including S.
        //
        //   The synchronization command that performs any necessary image layout transition
        //   includes S in both the srcStageMask and dstStageMask.
        flags |= VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
    }
    if (usage & kPresentReleaseTextureUsage) {
        // The present release usage is only used internally by the swapchain and is never used in
        // combination with other usages.
        DAWN_ASSERT(usage == kPresentReleaseTextureUsage);
        // The Vulkan spec has the following note:
        //
        //   When transitioning the image to VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR or
        //   VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, there is no need to delay subsequent
        //   processing, or perform any visibility operations (as vkQueuePresentKHR performs
        //   automatic visibility operations). To achieve this, the dstAccessMask member of
        //   the VkImageMemoryBarrier should be set to 0, and the dstStageMask parameter
        //   should be set to VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT.
        //
        // So on the transition to Present we use the "bottom of pipe" stage. The other
        // direction doesn't matter because swapchain textures always start a new frame
        // as uninitialized.
        flags |= VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT;
    }

    // A zero value isn't a valid pipeline stage mask
    DAWN_ASSERT(flags != 0);
    return flags;
}

VkImageMemoryBarrier BuildMemoryBarrier(const Texture* texture,
                                        wgpu::TextureUsage lastUsage,
                                        wgpu::TextureUsage usage,
                                        const SubresourceRange& range) {
    const Format& format = texture->GetFormat();

    VkImageMemoryBarrier barrier;
    barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
    barrier.pNext = nullptr;
    barrier.srcAccessMask = VulkanAccessFlags(lastUsage, format);
    barrier.dstAccessMask = VulkanAccessFlags(usage, format);
    barrier.oldLayout = texture->VulkanImageLayout(lastUsage);
    barrier.newLayout = texture->VulkanImageLayout(usage);
    barrier.image = texture->GetHandle();
    barrier.subresourceRange.aspectMask = VulkanAspectMask(range.aspects);
    barrier.subresourceRange.baseMipLevel = range.baseMipLevel;
    barrier.subresourceRange.levelCount = range.levelCount;
    barrier.subresourceRange.baseArrayLayer = range.baseArrayLayer;
    barrier.subresourceRange.layerCount = range.layerCount;

    barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    return barrier;
}

void FillVulkanCreateInfoSizesAndType(const Texture& texture, VkImageCreateInfo* info) {
    const Extent3D& size = texture.GetBaseSize();

    info->mipLevels = texture.GetNumMipLevels();
    info->samples = VulkanSampleCount(texture.GetSampleCount());

    // Fill in the image type, and paper over differences in how the array layer count is
    // specified between WebGPU and Vulkan.
    switch (texture.GetDimension()) {
        case wgpu::TextureDimension::Undefined:
            DAWN_UNREACHABLE();

        case wgpu::TextureDimension::e1D:
            info->imageType = VK_IMAGE_TYPE_1D;
            info->extent = {size.width, 1, 1};
            info->arrayLayers = 1;
            break;

        case wgpu::TextureDimension::e2D:
            info->imageType = VK_IMAGE_TYPE_2D;
            info->extent = {size.width, size.height, 1};
            info->arrayLayers = size.depthOrArrayLayers;
            break;

        case wgpu::TextureDimension::e3D:
            info->imageType = VK_IMAGE_TYPE_3D;
            info->extent = {size.width, size.height, size.depthOrArrayLayers};
            info->arrayLayers = 1;
            break;
    }
}

Aspect ComputeCombinedAspect(Device* device, const Format& format) {
    // In early Vulkan versions it is not possible to transition depth and stencil separately so
    // textures with Depth|Stencil will be promoted to a single CombinedDepthStencil aspect
    // internally.
    if (format.aspects == (Aspect::Depth | Aspect::Stencil)) {
        return Aspect::CombinedDepthStencil;
    }
    // Same thing for Stencil8 if it is emulated with a depth-stencil format and not directly S8.
    if (format.format == wgpu::TextureFormat::Stencil8 &&
        !device->IsToggleEnabled(Toggle::VulkanUseS8)) {
        return Aspect::CombinedDepthStencil;
    }

    // Some multiplanar images cannot have planes transitioned separately and instead Vulkan
    // requires that the "Color" aspect be used for barriers, so Plane0|Plane1|Plane2 is promoted to
    // just Color. The Vulkan spec requires: "If image has a single-plane color format or is not
    // disjoint, then the aspectMask member of subresourceRange must be VK_IMAGE_ASPECT_COLOR_BIT.".
    if (format.IsMultiPlanar()) {
        return Aspect::Color;
    }

    // No need to combine aspects.
    return Aspect::None;
}

VkComponentSwizzle VulkanComponentSwizzle(wgpu::ComponentSwizzle swizzle) {
    switch (swizzle) {
        case wgpu::ComponentSwizzle::Zero:
            return VK_COMPONENT_SWIZZLE_ZERO;
        case wgpu::ComponentSwizzle::One:
            return VK_COMPONENT_SWIZZLE_ONE;
        case wgpu::ComponentSwizzle::R:
            return VK_COMPONENT_SWIZZLE_R;
        case wgpu::ComponentSwizzle::G:
            return VK_COMPONENT_SWIZZLE_G;
        case wgpu::ComponentSwizzle::B:
            return VK_COMPONENT_SWIZZLE_B;
        case wgpu::ComponentSwizzle::A:
            return VK_COMPONENT_SWIZZLE_A;

        case wgpu::ComponentSwizzle::Undefined:
            DAWN_UNREACHABLE();
    }
    DAWN_UNREACHABLE();
}

void MaybeConvertDepthStencilSwizzleOneToAlpha(bool isDepthOrStencilFormat,
                                               const VulkanDeviceInfo& deviceInfo,
                                               wgpu::TextureComponentSwizzle* swizzle) {
    // Exit early if the format isn't depth or stencil.
    if (!isDepthOrStencilFormat) {
        return;
    }

    // Exit early if the device supports VK_COMPONENT_SWIZZLE_ONE for depth/stencil formats.
    // This is enabled by the VK_KHR_maintenance5 extension.
    // https://registry.khronos.org/vulkan/specs/latest/html/vkspec.html#textures-component-swizzle
    if (deviceInfo.HasExt(DeviceExt::Maintenance5) &&
        deviceInfo.propertiesMaintenance5.depthStencilSwizzleOneSupport == VK_TRUE) {
        return;
    }

    for (auto* componentPtr : {&swizzle->r, &swizzle->g, &swizzle->b, &swizzle->a}) {
        if (*componentPtr == wgpu::ComponentSwizzle::One) {
            // Convert 'One' to 'Alpha' (which typically samples as 1.0)
            // if the underlying Vulkan implementation doesn't support 'One' directly
            // for depth/stencil formats.
            *componentPtr = wgpu::ComponentSwizzle::A;
        }
    }
}

}  // namespace

#define SIMPLE_FORMAT_MAPPING(X)                                                      \
    X(wgpu::TextureFormat::R8Unorm, VK_FORMAT_R8_UNORM)                               \
    X(wgpu::TextureFormat::R8Snorm, VK_FORMAT_R8_SNORM)                               \
    X(wgpu::TextureFormat::R8Uint, VK_FORMAT_R8_UINT)                                 \
    X(wgpu::TextureFormat::R8Sint, VK_FORMAT_R8_SINT)                                 \
                                                                                      \
    X(wgpu::TextureFormat::R16Unorm, VK_FORMAT_R16_UNORM)                             \
    X(wgpu::TextureFormat::R16Snorm, VK_FORMAT_R16_SNORM)                             \
    X(wgpu::TextureFormat::R16Uint, VK_FORMAT_R16_UINT)                               \
    X(wgpu::TextureFormat::R16Sint, VK_FORMAT_R16_SINT)                               \
    X(wgpu::TextureFormat::R16Float, VK_FORMAT_R16_SFLOAT)                            \
    X(wgpu::TextureFormat::RG8Unorm, VK_FORMAT_R8G8_UNORM)                            \
    X(wgpu::TextureFormat::RG8Snorm, VK_FORMAT_R8G8_SNORM)                            \
    X(wgpu::TextureFormat::RG8Uint, VK_FORMAT_R8G8_UINT)                              \
    X(wgpu::TextureFormat::RG8Sint, VK_FORMAT_R8G8_SINT)                              \
                                                                                      \
    X(wgpu::TextureFormat::R32Uint, VK_FORMAT_R32_UINT)                               \
    X(wgpu::TextureFormat::R32Sint, VK_FORMAT_R32_SINT)                               \
    X(wgpu::TextureFormat::R32Float, VK_FORMAT_R32_SFLOAT)                            \
    X(wgpu::TextureFormat::RG16Unorm, VK_FORMAT_R16G16_UNORM)                         \
    X(wgpu::TextureFormat::RG16Snorm, VK_FORMAT_R16G16_SNORM)                         \
    X(wgpu::TextureFormat::RG16Uint, VK_FORMAT_R16G16_UINT)                           \
    X(wgpu::TextureFormat::RG16Sint, VK_FORMAT_R16G16_SINT)                           \
    X(wgpu::TextureFormat::RG16Float, VK_FORMAT_R16G16_SFLOAT)                        \
    X(wgpu::TextureFormat::RGBA8Unorm, VK_FORMAT_R8G8B8A8_UNORM)                      \
    X(wgpu::TextureFormat::RGBA8UnormSrgb, VK_FORMAT_R8G8B8A8_SRGB)                   \
    X(wgpu::TextureFormat::RGBA8Snorm, VK_FORMAT_R8G8B8A8_SNORM)                      \
    X(wgpu::TextureFormat::RGBA8Uint, VK_FORMAT_R8G8B8A8_UINT)                        \
    X(wgpu::TextureFormat::RGBA8Sint, VK_FORMAT_R8G8B8A8_SINT)                        \
    X(wgpu::TextureFormat::BGRA8Unorm, VK_FORMAT_B8G8R8A8_UNORM)                      \
    X(wgpu::TextureFormat::BGRA8UnormSrgb, VK_FORMAT_B8G8R8A8_SRGB)                   \
    X(wgpu::TextureFormat::RGB10A2Uint, VK_FORMAT_A2B10G10R10_UINT_PACK32)            \
    X(wgpu::TextureFormat::RGB10A2Unorm, VK_FORMAT_A2B10G10R10_UNORM_PACK32)          \
    X(wgpu::TextureFormat::RG11B10Ufloat, VK_FORMAT_B10G11R11_UFLOAT_PACK32)          \
    X(wgpu::TextureFormat::RGB9E5Ufloat, VK_FORMAT_E5B9G9R9_UFLOAT_PACK32)            \
                                                                                      \
    X(wgpu::TextureFormat::RG32Uint, VK_FORMAT_R32G32_UINT)                           \
    X(wgpu::TextureFormat::RG32Sint, VK_FORMAT_R32G32_SINT)                           \
    X(wgpu::TextureFormat::RG32Float, VK_FORMAT_R32G32_SFLOAT)                        \
    X(wgpu::TextureFormat::RGBA16Unorm, VK_FORMAT_R16G16B16A16_UNORM)                 \
    X(wgpu::TextureFormat::RGBA16Snorm, VK_FORMAT_R16G16B16A16_SNORM)                 \
    X(wgpu::TextureFormat::RGBA16Uint, VK_FORMAT_R16G16B16A16_UINT)                   \
    X(wgpu::TextureFormat::RGBA16Sint, VK_FORMAT_R16G16B16A16_SINT)                   \
    X(wgpu::TextureFormat::RGBA16Float, VK_FORMAT_R16G16B16A16_SFLOAT)                \
                                                                                      \
    X(wgpu::TextureFormat::RGBA32Uint, VK_FORMAT_R32G32B32A32_UINT)                   \
    X(wgpu::TextureFormat::RGBA32Sint, VK_FORMAT_R32G32B32A32_SINT)                   \
    X(wgpu::TextureFormat::RGBA32Float, VK_FORMAT_R32G32B32A32_SFLOAT)                \
                                                                                      \
    X(wgpu::TextureFormat::Depth16Unorm, VK_FORMAT_D16_UNORM)                         \
    X(wgpu::TextureFormat::Depth32Float, VK_FORMAT_D32_SFLOAT)                        \
    X(wgpu::TextureFormat::Depth32FloatStencil8, VK_FORMAT_D32_SFLOAT_S8_UINT)        \
                                                                                      \
    X(wgpu::TextureFormat::BC1RGBAUnorm, VK_FORMAT_BC1_RGBA_UNORM_BLOCK)              \
    X(wgpu::TextureFormat::BC1RGBAUnormSrgb, VK_FORMAT_BC1_RGBA_SRGB_BLOCK)           \
    X(wgpu::TextureFormat::BC2RGBAUnorm, VK_FORMAT_BC2_UNORM_BLOCK)                   \
    X(wgpu::TextureFormat::BC2RGBAUnormSrgb, VK_FORMAT_BC2_SRGB_BLOCK)                \
    X(wgpu::TextureFormat::BC3RGBAUnorm, VK_FORMAT_BC3_UNORM_BLOCK)                   \
    X(wgpu::TextureFormat::BC3RGBAUnormSrgb, VK_FORMAT_BC3_SRGB_BLOCK)                \
    X(wgpu::TextureFormat::BC4RSnorm, VK_FORMAT_BC4_SNORM_BLOCK)                      \
    X(wgpu::TextureFormat::BC4RUnorm, VK_FORMAT_BC4_UNORM_BLOCK)                      \
    X(wgpu::TextureFormat::BC5RGSnorm, VK_FORMAT_BC5_SNORM_BLOCK)                     \
    X(wgpu::TextureFormat::BC5RGUnorm, VK_FORMAT_BC5_UNORM_BLOCK)                     \
    X(wgpu::TextureFormat::BC6HRGBFloat, VK_FORMAT_BC6H_SFLOAT_BLOCK)                 \
    X(wgpu::TextureFormat::BC6HRGBUfloat, VK_FORMAT_BC6H_UFLOAT_BLOCK)                \
    X(wgpu::TextureFormat::BC7RGBAUnorm, VK_FORMAT_BC7_UNORM_BLOCK)                   \
    X(wgpu::TextureFormat::BC7RGBAUnormSrgb, VK_FORMAT_BC7_SRGB_BLOCK)                \
                                                                                      \
    X(wgpu::TextureFormat::ETC2RGB8Unorm, VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK)          \
    X(wgpu::TextureFormat::ETC2RGB8UnormSrgb, VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK)       \
    X(wgpu::TextureFormat::ETC2RGB8A1Unorm, VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK)      \
    X(wgpu::TextureFormat::ETC2RGB8A1UnormSrgb, VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK)   \
    X(wgpu::TextureFormat::ETC2RGBA8Unorm, VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK)       \
    X(wgpu::TextureFormat::ETC2RGBA8UnormSrgb, VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK)    \
    X(wgpu::TextureFormat::EACR11Unorm, VK_FORMAT_EAC_R11_UNORM_BLOCK)                \
    X(wgpu::TextureFormat::EACR11Snorm, VK_FORMAT_EAC_R11_SNORM_BLOCK)                \
    X(wgpu::TextureFormat::EACRG11Unorm, VK_FORMAT_EAC_R11G11_UNORM_BLOCK)            \
    X(wgpu::TextureFormat::EACRG11Snorm, VK_FORMAT_EAC_R11G11_SNORM_BLOCK)            \
                                                                                      \
    X(wgpu::TextureFormat::ASTC4x4Unorm, VK_FORMAT_ASTC_4x4_UNORM_BLOCK)              \
    X(wgpu::TextureFormat::ASTC4x4UnormSrgb, VK_FORMAT_ASTC_4x4_SRGB_BLOCK)           \
    X(wgpu::TextureFormat::ASTC5x4Unorm, VK_FORMAT_ASTC_5x4_UNORM_BLOCK)              \
    X(wgpu::TextureFormat::ASTC5x4UnormSrgb, VK_FORMAT_ASTC_5x4_SRGB_BLOCK)           \
    X(wgpu::TextureFormat::ASTC5x5Unorm, VK_FORMAT_ASTC_5x5_UNORM_BLOCK)              \
    X(wgpu::TextureFormat::ASTC5x5UnormSrgb, VK_FORMAT_ASTC_5x5_SRGB_BLOCK)           \
    X(wgpu::TextureFormat::ASTC6x5Unorm, VK_FORMAT_ASTC_6x5_UNORM_BLOCK)              \
    X(wgpu::TextureFormat::ASTC6x5UnormSrgb, VK_FORMAT_ASTC_6x5_SRGB_BLOCK)           \
    X(wgpu::TextureFormat::ASTC6x6Unorm, VK_FORMAT_ASTC_6x6_UNORM_BLOCK)              \
    X(wgpu::TextureFormat::ASTC6x6UnormSrgb, VK_FORMAT_ASTC_6x6_SRGB_BLOCK)           \
    X(wgpu::TextureFormat::ASTC8x5Unorm, VK_FORMAT_ASTC_8x5_UNORM_BLOCK)              \
    X(wgpu::TextureFormat::ASTC8x5UnormSrgb, VK_FORMAT_ASTC_8x5_SRGB_BLOCK)           \
    X(wgpu::TextureFormat::ASTC8x6Unorm, VK_FORMAT_ASTC_8x6_UNORM_BLOCK)              \
    X(wgpu::TextureFormat::ASTC8x6UnormSrgb, VK_FORMAT_ASTC_8x6_SRGB_BLOCK)           \
    X(wgpu::TextureFormat::ASTC8x8Unorm, VK_FORMAT_ASTC_8x8_UNORM_BLOCK)              \
    X(wgpu::TextureFormat::ASTC8x8UnormSrgb, VK_FORMAT_ASTC_8x8_SRGB_BLOCK)           \
    X(wgpu::TextureFormat::ASTC10x5Unorm, VK_FORMAT_ASTC_10x5_UNORM_BLOCK)            \
    X(wgpu::TextureFormat::ASTC10x5UnormSrgb, VK_FORMAT_ASTC_10x5_SRGB_BLOCK)         \
    X(wgpu::TextureFormat::ASTC10x6Unorm, VK_FORMAT_ASTC_10x6_UNORM_BLOCK)            \
    X(wgpu::TextureFormat::ASTC10x6UnormSrgb, VK_FORMAT_ASTC_10x6_SRGB_BLOCK)         \
    X(wgpu::TextureFormat::ASTC10x8Unorm, VK_FORMAT_ASTC_10x8_UNORM_BLOCK)            \
    X(wgpu::TextureFormat::ASTC10x8UnormSrgb, VK_FORMAT_ASTC_10x8_SRGB_BLOCK)         \
    X(wgpu::TextureFormat::ASTC10x10Unorm, VK_FORMAT_ASTC_10x10_UNORM_BLOCK)          \
    X(wgpu::TextureFormat::ASTC10x10UnormSrgb, VK_FORMAT_ASTC_10x10_SRGB_BLOCK)       \
    X(wgpu::TextureFormat::ASTC12x10Unorm, VK_FORMAT_ASTC_12x10_UNORM_BLOCK)          \
    X(wgpu::TextureFormat::ASTC12x10UnormSrgb, VK_FORMAT_ASTC_12x10_SRGB_BLOCK)       \
    X(wgpu::TextureFormat::ASTC12x12Unorm, VK_FORMAT_ASTC_12x12_UNORM_BLOCK)          \
    X(wgpu::TextureFormat::ASTC12x12UnormSrgb, VK_FORMAT_ASTC_12x12_SRGB_BLOCK)       \
                                                                                      \
    X(wgpu::TextureFormat::R8BG8Biplanar420Unorm, VK_FORMAT_G8_B8R8_2PLANE_420_UNORM) \
    X(wgpu::TextureFormat::R8BG8Biplanar422Unorm, VK_FORMAT_G8_B8R8_2PLANE_422_UNORM) \
    X(wgpu::TextureFormat::R8BG8Biplanar444Unorm, VK_FORMAT_G8_B8R8_2PLANE_444_UNORM) \
    X(wgpu::TextureFormat::R10X6BG10X6Biplanar420Unorm,                               \
      VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16)                            \
    X(wgpu::TextureFormat::R10X6BG10X6Biplanar422Unorm,                               \
      VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16)                            \
    X(wgpu::TextureFormat::R10X6BG10X6Biplanar444Unorm,                               \
      VK_FORMAT_G10X6_B10X6R10X6_2PLANE_444_UNORM_3PACK16)

// Converts Dawn texture format to Vulkan formats.
VkFormat VulkanImageFormat(const Device* device, wgpu::TextureFormat format) {
    switch (format) {
#define X(wgpuFormat, vkFormat) \
    case wgpuFormat:            \
        return vkFormat;
        SIMPLE_FORMAT_MAPPING(X)
#undef X
        case wgpu::TextureFormat::Depth24PlusStencil8:
            // Depth24PlusStencil8 maps to either of these two formats because only requires
            // that one of the two be present. The VulkanUseD32S8 toggle combines the wish of
            // the environment, default to using D32S8, and availability information so we know
            // that the format is available.
            if (device->IsToggleEnabled(Toggle::VulkanUseD32S8)) {
                return VK_FORMAT_D32_SFLOAT_S8_UINT;
            } else {
                return VK_FORMAT_D24_UNORM_S8_UINT;
            }

        case wgpu::TextureFormat::Depth24Plus:
            return VK_FORMAT_D32_SFLOAT;

        case wgpu::TextureFormat::Stencil8:
            // Try to use the stencil8 format if possible, otherwise use whatever format we can
            // use that contains a stencil8 component.
            if (device->IsToggleEnabled(Toggle::VulkanUseS8)) {
                return VK_FORMAT_S8_UINT;
            } else {
                return VulkanImageFormat(device, wgpu::TextureFormat::Depth24PlusStencil8);
            }

        case wgpu::TextureFormat::OpaqueYCbCrAndroid:
            // The VkFormat is Undefined when TextureFormat::OpaqueYCbCrAndroid is passed for YCbCr
            // samplers.
            return VK_FORMAT_UNDEFINED;

        // R8BG8A8Triplanar420Unorm format is only supported on macOS.
        case wgpu::TextureFormat::R8BG8A8Triplanar420Unorm:
        case wgpu::TextureFormat::Undefined:
            break;
    }
    DAWN_UNREACHABLE();
}

// Converts Dawn texture format to Vulkan formats.
VkFormat ColorVulkanImageFormat(wgpu::TextureFormat format) {
    switch (format) {
#define X(wgpuFormat, vkFormat) \
    case wgpuFormat:            \
        return vkFormat;
        SIMPLE_FORMAT_MAPPING(X)
#undef X
        default:
            return VK_FORMAT_UNDEFINED;
    }
    DAWN_UNREACHABLE();
}

ResultOrError<wgpu::TextureFormat> FormatFromVkFormat(const Device* device, VkFormat vkFormat) {
    switch (vkFormat) {
#define X(wgpuFormat, vkFormat) \
    case vkFormat:              \
        return wgpuFormat;
        SIMPLE_FORMAT_MAPPING(X)
#undef X
        case VK_FORMAT_S8_UINT:
            if (device->IsToggleEnabled(Toggle::VulkanUseS8)) {
                return wgpu::TextureFormat::Stencil8;
            }
            break;

        case VK_FORMAT_D24_UNORM_S8_UINT:
            if (!device->IsToggleEnabled(Toggle::VulkanUseD32S8)) {
                return wgpu::TextureFormat::Depth24PlusStencil8;
            }
            break;

        default:
            break;
    }
    return DAWN_VALIDATION_ERROR("Unsupported VkFormat %x", vkFormat);
}

#undef SIMPLE_FORMAT_MAPPING

// Converts the Dawn usage flags to Vulkan usage flags. Also needs the format to choose
// between color and depth attachment usages.
VkImageUsageFlags VulkanImageUsage(const DeviceBase* device,
                                   wgpu::TextureUsage usage,
                                   const Format& format) {
    VkImageUsageFlags flags = 0;

    if (usage & wgpu::TextureUsage::CopySrc) {
        flags |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
    }
    if (usage & wgpu::TextureUsage::CopyDst) {
        flags |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
    }
    if (usage & wgpu::TextureUsage::TextureBinding) {
        flags |= VK_IMAGE_USAGE_SAMPLED_BIT;
        // If the sampled texture is a depth/stencil texture, its image layout will be set
        // to DEPTH_STENCIL_READ_ONLY_OPTIMAL in order to support readonly depth/stencil
        // attachment. That layout requires DEPTH_STENCIL_ATTACHMENT_BIT image usage.
        if (format.HasDepthOrStencil() && format.IsRenderable()) {
            flags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
        }
    }
    if (usage & wgpu::TextureUsage::StorageBinding) {
        // Storage bit should only be included if the format actually supports a storage uage.
        DAWN_ASSERT(format.SupportsReadOnlyStorageUsage() ||
                    format.SupportsWriteOnlyStorageUsage());
        flags |= VK_IMAGE_USAGE_STORAGE_BIT;
    }
    if (usage & wgpu::TextureUsage::RenderAttachment) {
        if (format.HasDepthOrStencil()) {
            flags |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
        } else {
            flags |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;

            // Automatically set "input attachment" usage so that the texture can be used in
            // ExpandResolveTexture subpass or with framebuffer fetch.
            bool mayNeedToExpandTexture = !format.IsMultiPlanar() &&
                                          usage & wgpu::TextureUsage::TextureBinding &&
                                          device->HasFeature(Feature::DawnLoadResolveTexture);
            if (mayNeedToExpandTexture || device->HasFeature(Feature::FramebufferFetch)) {
                flags |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
            }
        }
    }
    if (usage & wgpu::TextureUsage::TransientAttachment) {
        flags |= VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT;
    }

    // Choosing Vulkan image usages should not know about kReadOnlyRenderAttachment because that's
    // a property of when the image is used, not of the creation.
    DAWN_ASSERT(!(usage & kReadOnlyRenderAttachment));

    return flags;
}

VkImageCreateFlags VulkanImageCreateFlags(const DeviceBase* device,
                                          wgpu::TextureUsage usage,
                                          const Format& format,
                                          uint32_t sampleCount) {
    VkImageCreateFlags vkCreateFlags = 0;

    // If the MSAARenderToSingleSampled feature is enabled, textures with RenderAttachment usage
    // need to have the VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT flag set so
    // that they can be used as a render target with an implicit sample count. syoussefi@ has
    // confirmed that this is expected to be cheap or no cost on hardware with the extension.
    if (device->HasFeature(Feature::MSAARenderToSingleSampled) &&
        (usage & wgpu::TextureUsage::RenderAttachment) && sampleCount == 1 &&
        !format.HasDepthOrStencil()) {
        vkCreateFlags |= VK_IMAGE_CREATE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_BIT_EXT;
    }

    return vkCreateFlags;
}

// Chooses which Vulkan image layout should be used for the given Dawn usage. Note that this
// layout must match the layout given to various Vulkan operations as well as the layout given
// to descriptor set writes.
VkImageLayout VulkanImageLayout(const Format& format,
                                wgpu::TextureUsage usage,
                                wgpu::TextureUsage allowedUsage = wgpu::TextureUsage::None) {
    if (allowedUsage == wgpu::TextureUsage::None) {
        allowedUsage = usage;
    }

    // Note some of these cases have one bit, others have multiple bits.
#if DAWN_COMPILER_IS(CLANG)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wswitch"
#endif
    switch (usage) {
        case wgpu::TextureUsage::None:
            return VK_IMAGE_LAYOUT_UNDEFINED;

        case wgpu::TextureUsage::CopyDst:
            return VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;

            // The layout returned here is the one that will be used at bindgroup creation time.
        case wgpu::TextureUsage::TextureBinding:
        case kResolveAttachmentLoadingUsage:
            // The sampled image can be used as a readonly depth/stencil attachment at the same
            // time if it is a depth/stencil renderable format, so the image layout need to be
            // VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL.
            if (format.HasDepthOrStencil() && format.IsRenderable()) {
                return VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
            }
            // Sampled textures can be used simultaneously as read only storage. If storage usage is
            // allowed fall back to VK_IMAGE_LAYOUT_GENERAL.
            // TODO(crbug.com/392121643): Investigate potential optimizations.
            if (allowedUsage & (wgpu::TextureUsage::StorageBinding | kReadOnlyStorageTexture)) {
                return VK_IMAGE_LAYOUT_GENERAL;
            }
            return VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;

            // Vulkan texture copy functions require the image to be in _one_  known layout.
            // Depending on whether parts of the texture have been transitioned to only CopySrc
            // or a combination with something else, the texture could be in a combination of
            // GENERAL and TRANSFER_SRC_OPTIMAL. This would be a problem, so we make CopySrc use
            // GENERAL.
            // TODO(crbug.com/dawn/851): We no longer need to transition resources all at
            // once and can instead track subresources so we should lift this limitation.
        case wgpu::TextureUsage::CopySrc:
            // Read-only and write-only storage textures must use general layout because load
            // and store operations on storage images can only be done on the images in
            // VK_IMAGE_LAYOUT_GENERAL layout.
        case wgpu::TextureUsage::StorageBinding:
        case kReadOnlyStorageTexture:
        case kReadOnlyStorageTexture | wgpu::TextureUsage::TextureBinding:
        case kWriteOnlyStorageTexture:
            return VK_IMAGE_LAYOUT_GENERAL;

        case wgpu::TextureUsage::RenderAttachment:
            if (format.HasDepthOrStencil()) {
                return VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
            } else {
                return VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
            }

        case kDepthReadOnlyStencilWritableAttachment:
        case kDepthReadOnlyStencilWritableAttachment | wgpu::TextureUsage::TextureBinding:
            return VK_IMAGE_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_OPTIMAL;
        case kDepthWritableStencilReadOnlyAttachment:
        case kDepthWritableStencilReadOnlyAttachment | wgpu::TextureUsage::TextureBinding:
            return VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_OPTIMAL;
        case kReadOnlyRenderAttachment:
        case kReadOnlyRenderAttachment | wgpu::TextureUsage::TextureBinding:
            return VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;

        case kPresentReleaseTextureUsage:
            return VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
        case kPresentAcquireTextureUsage:
            // We always consider images being acquired from the swapchain as uninitialized,
            // so we can use the UNDEFINED Vulkan image layout.
            return VK_IMAGE_LAYOUT_UNDEFINED;

        case wgpu::TextureUsage::TransientAttachment:
            // Will be covered by RenderAttachment above, as specification of
            // TransientAttachment requires that RenderAttachment also be
            // specified.
            DAWN_UNREACHABLE();
            break;

        case wgpu::TextureUsage::StorageAttachment:
            // TODO(dawn:1704): Support PLS on Vulkan.
            DAWN_UNREACHABLE();
    }
#if DAWN_COMPILER_IS(CLANG)
#pragma clang diagnostic pop
#endif
    DAWN_UNREACHABLE();
}

VkImageLayout VulkanImageLayoutForDepthStencilAttachment(const Format& format,
                                                         bool depthReadOnly,
                                                         bool stencilReadOnly) {
    wgpu::TextureUsage depth = wgpu::TextureUsage::None;
    if (format.HasDepth()) {
        depth = depthReadOnly ? kReadOnlyRenderAttachment : wgpu::TextureUsage::RenderAttachment;
    }

    wgpu::TextureUsage stencil = wgpu::TextureUsage::None;
    if (format.HasStencil()) {
        stencil =
            stencilReadOnly ? kReadOnlyRenderAttachment : wgpu::TextureUsage::RenderAttachment;
    }

    return VulkanImageLayout(format, MergeDepthStencilUsage(depth, stencil));
}

VkSampleCountFlagBits VulkanSampleCount(uint32_t sampleCount) {
    switch (sampleCount) {
        case 1:
            return VK_SAMPLE_COUNT_1_BIT;
        case 4:
            return VK_SAMPLE_COUNT_4_BIT;
    }
    DAWN_UNREACHABLE();
}

MaybeError ValidateVulkanImageCanBeWrapped(const DeviceBase*,
                                           const UnpackedPtr<TextureDescriptor>& descriptor) {
    DAWN_INVALID_IF(descriptor->dimension != wgpu::TextureDimension::e2D,
                    "Texture dimension (%s) is not %s.", descriptor->dimension,
                    wgpu::TextureDimension::e2D);

    DAWN_INVALID_IF(descriptor->mipLevelCount != 1, "Mip level count (%u) is not 1.",
                    descriptor->mipLevelCount);

    DAWN_INVALID_IF(descriptor->size.depthOrArrayLayers != 1, "Array layer count (%u) is not 1.",
                    descriptor->size.depthOrArrayLayers);

    DAWN_INVALID_IF(descriptor->sampleCount != 1, "Sample count (%u) is not 1.",
                    descriptor->sampleCount);

    return {};
}

bool IsSampleCountSupported(const dawn::native::vulkan::Device* device,
                            const VkImageCreateInfo& imageCreateInfo) {
    DAWN_ASSERT(device);

    VkPhysicalDevice vkPhysicalDevice =
        ToBackend(device->GetPhysicalDevice())->GetVkPhysicalDevice();
    VkImageFormatProperties properties;
    if (device->fn.GetPhysicalDeviceImageFormatProperties(
            vkPhysicalDevice, imageCreateInfo.format, imageCreateInfo.imageType,
            imageCreateInfo.tiling, imageCreateInfo.usage, imageCreateInfo.flags,
            &properties) != VK_SUCCESS) {
        DAWN_UNREACHABLE();
    }

    return (properties.sampleCounts & imageCreateInfo.samples) != 0u;
}

Texture::Texture(Device* device, const UnpackedPtr<TextureDescriptor>& descriptor)
    : TextureBase(device, descriptor),
      mCombinedAspect(ComputeCombinedAspect(device, GetFormat())),
      // A usage of none will make sure the texture is transitioned before its first use as
      // required by the Vulkan spec.
      mSubresourceLastSyncInfos(
          mCombinedAspect != Aspect::None ? mCombinedAspect : GetFormat().aspects,
          GetArrayLayers(),
          GetNumMipLevels(),
          TextureSyncInfo{wgpu::TextureUsage::None, wgpu::ShaderStage::None}) {}

void Texture::SetLabelHelper(const char* prefix) {
    SetDebugName(ToBackend(GetDevice()), mHandle, prefix, GetLabel());
}

void Texture::NotifySwapChainPresent() {
    // When using an external swap chain texture, there's no way to determine frame boundaries since
    // Dawn isn't managing the Vulkan swap chains. In this mode, external tools like RenderDoc
    // will wait forever for a present that never happens. We handle this by using tool-specific
    // hooks to inform them of the "presented" texture so it can determine frame
    // boundaries and use its contents for the UI.
    if (!mIsExternalSwapChainTexture) {
        return;
    }

#if defined(DAWN_ENABLE_RENDERDOC)
    Device* device = ToBackend(GetDevice());

    // For RenderDoc, we expect the user to enable and use process injection to inject RenderDoc
    // into the GPU process at startup. We start capturing all frames right away. The user has
    // to kill the process or stop it from rendering (e.g. close or change tabs in Chrome).
    if (auto renderDocApi = dawn::native::utils::GetRenderDocApi(device)) {
        void* renderDocDevicePtr = RENDERDOC_DEVICEPOINTER_FROM_VKINSTANCE(device->GetVkInstance());

        // We signal the end of the current frame and the start of the next.
        // This means we miss capturing the very first frame.
        renderDocApi->EndFrameCapture(renderDocDevicePtr, nullptr);
        renderDocApi->StartFrameCapture(renderDocDevicePtr, nullptr);
    }
#endif
}

void Texture::SetIsExternalSwapchainTexture(bool isSwapChainTexture) {
    mIsExternalSwapChainTexture = isSwapChainTexture;
}

VkImageLayout Texture::VulkanImageLayout(wgpu::TextureUsage usage) const {
    return dawn::native::vulkan::VulkanImageLayout(GetFormat(), usage, GetUsage());
}

void Texture::SetLabelImpl() {
    SetLabelHelper("Dawn_InternalTexture");
}

void Texture::DestroyImpl(DestroyReason reason) {
    // TODO(crbug.com/dawn/831): DestroyImpl is called from two places.
    // - It may be called if the texture is explicitly destroyed with APIDestroy.
    //   This case is NOT thread-safe and needs proper synchronization with other
    //   simultaneous uses of the texture.
    // - It may be called when the last ref to the texture is dropped and the texture
    //   is implicitly destroyed. This case is thread-safe because there are no
    //   other threads using the texture since there are no other live refs.
    mHandle = VK_NULL_HANDLE;
    mIsExternalSwapChainTexture = false;

    TextureBase::DestroyImpl(reason);
}

VkImage Texture::GetHandle() const {
    return mHandle;
}

bool Texture::CanReuseWithoutBarrier(wgpu::TextureUsage lastUsage,
                                     wgpu::TextureUsage usage,
                                     wgpu::ShaderStage lastShaderStage,
                                     wgpu::ShaderStage shaderStage) {
    // Reuse the texture directly and avoid encoding barriers when it isn't needed.
    bool lastReadOnly = IsSubset(lastUsage, kReadOnlyTextureUsages);
    return lastReadOnly && lastUsage == usage && IsSubset(shaderStage, lastShaderStage);
}

void Texture::TransitionUsageForPass(CommandRecordingContext* recordingContext,
                                     const TextureSubresourceSyncInfo& textureSyncInfos,
                                     std::vector<VkImageMemoryBarrier>* imageBarriers,
                                     VkPipelineStageFlags* srcStages,
                                     VkPipelineStageFlags* dstStages) {
    if (!UseCombinedAspects()) {
        TransitionUsageForPassImpl(recordingContext, textureSyncInfos, imageBarriers, srcStages,
                                   dstStages);
        return;
    }
    // We need to combine aspects for the transition, use a new subresource storage that will
    // contain the combined usages for the aspects.
    SubresourceStorage<TextureSyncInfo> combinedUsages(mCombinedAspect, GetArrayLayers(),
                                                       GetNumMipLevels());
    if (mCombinedAspect == Aspect::CombinedDepthStencil) {
        // For depth-stencil we can't just combine the aspect with an | operation because there
        // needs to be special handling for readonly aspects. Instead figure out which aspect is
        // currently being added (and which one is already present) and call the custom merging
        // function for depth-stencil.
        textureSyncInfos.Iterate([&](const SubresourceRange& range, TextureSyncInfo syncInfo) {
            SubresourceRange updateRange = range;
            updateRange.aspects = mCombinedAspect;
            Aspect aspectsToMerge = range.aspects;
            combinedUsages.Update(
                updateRange, [&](const SubresourceRange&, TextureSyncInfo* combinedInfo) {
                    if (aspectsToMerge == Aspect::Depth) {
                        combinedInfo->usage =
                            MergeDepthStencilUsage(syncInfo.usage, combinedInfo->usage);
                    } else if (aspectsToMerge == Aspect::Stencil) {
                        combinedInfo->usage =
                            MergeDepthStencilUsage(combinedInfo->usage, syncInfo.usage);
                    } else {
                        DAWN_ASSERT(aspectsToMerge == (Aspect::Depth | Aspect::Stencil));
                        combinedInfo->usage = syncInfo.usage;
                    }
                    combinedInfo->shaderStages |= syncInfo.shaderStages;
                });
        });
    } else {
        // Combine aspect's usages with the | operation.
        textureSyncInfos.Iterate([&](const SubresourceRange& range, TextureSyncInfo syncInfo) {
            SubresourceRange updateRange = range;
            updateRange.aspects = mCombinedAspect;
            combinedUsages.Update(updateRange,
                                  [&](const SubresourceRange&, TextureSyncInfo* combinedInfo) {
                                      combinedInfo->usage |= syncInfo.usage;
                                      combinedInfo->shaderStages |= syncInfo.shaderStages;
                                  });
        });
    }
    TransitionUsageForPassImpl(recordingContext, combinedUsages, imageBarriers, srcStages,
                               dstStages);
}

void Texture::TransitionUsageForPassImpl(
    CommandRecordingContext* recordingContext,
    const SubresourceStorage<TextureSyncInfo>& subresourceSyncInfos,
    std::vector<VkImageMemoryBarrier>* imageBarriers,
    VkPipelineStageFlags* srcStages,
    VkPipelineStageFlags* dstStages) {
    size_t transitionBarrierStart = imageBarriers->size();
    const Format& format = GetFormat();

    wgpu::TextureUsage allNewUsages = wgpu::TextureUsage::None;
    wgpu::TextureUsage allLastUsages = wgpu::TextureUsage::None;

    wgpu::ShaderStage allNewShaderStages = wgpu::ShaderStage::None;
    wgpu::ShaderStage allLastShaderStages = wgpu::ShaderStage::None;

    mSubresourceLastSyncInfos.Merge(subresourceSyncInfos, [&](const SubresourceRange& range,
                                                              TextureSyncInfo* lastSyncInfo,
                                                              const TextureSyncInfo& newSyncInfo) {
        wgpu::TextureUsage newUsage = newSyncInfo.usage;
        if (newSyncInfo.shaderStages == wgpu::ShaderStage::None) {
            // If the image isn't used in any shader stages, ignore shader usages. Eg. ignore a
            // texture binding that isn't actually sampled in any shader.
            newUsage &= ~kShaderTextureUsages;
        }

        if (newUsage == wgpu::TextureUsage::None ||
            CanReuseWithoutBarrier(lastSyncInfo->usage, newUsage, lastSyncInfo->shaderStages,
                                   newSyncInfo.shaderStages)) {
            return;
        }

        imageBarriers->push_back(BuildMemoryBarrier(this, lastSyncInfo->usage, newUsage, range));

        allLastUsages |= lastSyncInfo->usage;
        allNewUsages |= newUsage;

        allLastShaderStages |= lastSyncInfo->shaderStages;
        allNewShaderStages |= newSyncInfo.shaderStages;

        if (lastSyncInfo->usage == newUsage &&
            IsSubset(lastSyncInfo->usage, kReadOnlyTextureUsages)) {
            // Read only usage and no layout transition. We can keep previous shader stages so
            // future uses in those stages don't insert barriers.
            lastSyncInfo->shaderStages |= newSyncInfo.shaderStages;
        } else {
            // Image was altered by write or layout transition. We need to clear previous shader
            // stages so future uses in those stages will insert barriers.
            lastSyncInfo->shaderStages = newSyncInfo.shaderStages;
        }
        lastSyncInfo->usage = newUsage;
    });

    TweakTransition(recordingContext, imageBarriers, transitionBarrierStart);

    // Skip adding pipeline stages if no barrier was needed to avoid putting TOP_OF_PIPE in the
    // destination stages.
    if (allNewUsages != wgpu::TextureUsage::None) {
        *srcStages |= VulkanPipelineStage(allLastUsages, allLastShaderStages, format);
        *dstStages |= VulkanPipelineStage(allNewUsages, allNewShaderStages, format);
    }
}

void Texture::TransitionUsageNow(CommandRecordingContext* recordingContext,
                                 wgpu::TextureUsage usage,
                                 wgpu::ShaderStage shaderStages,
                                 const SubresourceRange& range) {
    std::vector<VkImageMemoryBarrier> barriers;

    VkPipelineStageFlags srcStages = 0;
    VkPipelineStageFlags dstStages = 0;

    TransitionUsageAndGetResourceBarrier(usage, shaderStages, range, &barriers, &srcStages,
                                         &dstStages);

    TweakTransition(recordingContext, &barriers, 0);

    if (!barriers.empty()) {
        DAWN_ASSERT(srcStages != 0 && dstStages != 0);
        ToBackend(GetDevice())
            ->fn.CmdPipelineBarrier(recordingContext->commandBuffer, srcStages, dstStages, 0, 0,
                                    nullptr, 0, nullptr, barriers.size(), barriers.data());
    }
}

void Texture::UpdateUsage(wgpu::TextureUsage usage,
                          wgpu::ShaderStage shaderStages,
                          const SubresourceRange& range) {
    std::vector<VkImageMemoryBarrier> barriers;

    VkPipelineStageFlags srcStages = 0;
    VkPipelineStageFlags dstStages = 0;

    TransitionUsageAndGetResourceBarrier(usage, shaderStages, range, &barriers, &srcStages,
                                         &dstStages);

    // barriers are ignored.
}

void Texture::TransitionUsageAndGetResourceBarrier(wgpu::TextureUsage usage,
                                                   wgpu::ShaderStage shaderStages,
                                                   const SubresourceRange& range,
                                                   std::vector<VkImageMemoryBarrier>* imageBarriers,
                                                   VkPipelineStageFlags* srcStages,
                                                   VkPipelineStageFlags* dstStages) {
    if (UseCombinedAspects()) {
        SubresourceRange updatedRange = range;
        updatedRange.aspects = mCombinedAspect;
        TransitionUsageAndGetResourceBarrierImpl(usage, shaderStages, updatedRange, imageBarriers,
                                                 srcStages, dstStages);
    } else {
        TransitionUsageAndGetResourceBarrierImpl(usage, shaderStages, range, imageBarriers,
                                                 srcStages, dstStages);
    }
}

void Texture::TransitionUsageAndGetResourceBarrierImpl(
    wgpu::TextureUsage usage,
    wgpu::ShaderStage shaderStages,
    const SubresourceRange& range,
    std::vector<VkImageMemoryBarrier>* imageBarriers,
    VkPipelineStageFlags* srcStages,
    VkPipelineStageFlags* dstStages) {
    DAWN_ASSERT(imageBarriers != nullptr);
    const Format& format = GetFormat();

    if (shaderStages == wgpu::ShaderStage::None) {
        // If the image isn't used in any shader stages, ignore shader usages. Eg. ignore a texture
        // binding that isn't actually sampled in any shader.
        usage &= ~kShaderTextureUsages;
    }

    wgpu::TextureUsage allLastUsages = wgpu::TextureUsage::None;
    wgpu::ShaderStage allLastShaderStages = wgpu::ShaderStage::None;
    mSubresourceLastSyncInfos.Update(
        range, [&](const SubresourceRange& range, TextureSyncInfo* lastSyncInfo) {
            if (CanReuseWithoutBarrier(lastSyncInfo->usage, usage, lastSyncInfo->shaderStages,
                                       shaderStages)) {
                return;
            }

            imageBarriers->push_back(BuildMemoryBarrier(this, lastSyncInfo->usage, usage, range));

            allLastUsages |= lastSyncInfo->usage;
            allLastShaderStages |= lastSyncInfo->shaderStages;

            if (lastSyncInfo->usage == usage && IsSubset(usage, kReadOnlyTextureUsages)) {
                // Read only usage and no layout transition. We can keep previous shader stages so
                // future uses in those stages don't insert barriers.
                lastSyncInfo->shaderStages |= shaderStages;
            } else {
                // Image was altered by write or layout transition. We need to clear previous shader
                // stages so future uses in those stages will insert barriers.
                lastSyncInfo->shaderStages = shaderStages;
            }
            lastSyncInfo->usage = usage;
        });

    *srcStages |= VulkanPipelineStage(allLastUsages, allLastShaderStages, format);
    *dstStages |= VulkanPipelineStage(usage, shaderStages, format);
}

MaybeError Texture::ClearTexture(CommandRecordingContext* recordingContext,
                                 const SubresourceRange& range,
                                 TextureBase::ClearValue clearValue) {
    Device* device = ToBackend(GetDevice());

    const bool isZero = clearValue == TextureBase::ClearValue::Zero;
    uint32_t uClearColor = isZero ? 0 : 1;
    float fClearColor = isZero ? 0.f : 1.f;
    double dClearColor = double{fClearColor};

    VkImageSubresourceRange imageRange = {};
    imageRange.levelCount = 1;
    imageRange.layerCount = 1;

    if ((GetInternalUsage() & wgpu::TextureUsage::RenderAttachment) && GetFormat().IsColor() &&
        !GetFormat().IsMultiPlanar()) {
        TransitionUsageNow(recordingContext, wgpu::TextureUsage::RenderAttachment,
                           wgpu::ShaderStage::None, range);

        for (uint32_t level = range.baseMipLevel; level < range.baseMipLevel + range.levelCount;
             ++level) {
            for (uint32_t layer = range.baseArrayLayer;
                 layer < range.baseArrayLayer + range.layerCount; ++layer) {
                Aspect aspects = Aspect::None;
                for (Aspect aspect : IterateEnumMask(range.aspects)) {
                    if (clearValue == TextureBase::ClearValue::Zero &&
                        IsSubresourceContentInitialized(
                            SubresourceRange::SingleMipAndLayer(level, layer, aspect))) {
                        // Skip lazy clears if already initialized.
                        continue;
                    }
                    aspects |= aspect;
                }

                if (aspects == Aspect::None) {
                    continue;
                }

                Extent3D mipSize = GetMipLevelSingleSubresourcePhysicalSize(level, aspects);
                BeginRenderPassCmd beginCmd{};
                beginCmd.width = mipSize.width;
                beginCmd.height = mipSize.height;
                beginCmd.renderArea = {0, 0, mipSize.width, mipSize.height};

                TextureViewDescriptor viewDesc = {};
                viewDesc.label = "Dawn_ClearTexture_View";
                viewDesc.format = GetFormat().format;

                uint32_t depthSliceCount = 1;
                switch (GetDimension()) {
                    case wgpu::TextureDimension::e2D:
                        viewDesc.dimension = wgpu::TextureViewDimension::e2D;
                        break;
                    case wgpu::TextureDimension::e3D:
                        viewDesc.dimension = wgpu::TextureViewDimension::e3D;
                        depthSliceCount = mipSize.depthOrArrayLayers;
                        DAWN_ASSERT(layer == 0);
                        break;
                    case wgpu::TextureDimension::e1D:
                    case wgpu::TextureDimension::Undefined:
                        DAWN_UNREACHABLE();
                        break;
                }

                viewDesc.baseMipLevel = level;
                viewDesc.mipLevelCount = 1u;
                viewDesc.baseArrayLayer = layer;
                viewDesc.arrayLayerCount = 1u;
                // Inherit wgpu::TextureUsage::RenderAttachment, which may be an internal usage.
                viewDesc.usage = wgpu::TextureUsage::None;

                ColorAttachmentIndex ca0(uint8_t(0));
                DAWN_TRY_ASSIGN(beginCmd.colorAttachments[ca0].view,
                                device->CreateTextureView(this, &viewDesc));

                RenderPassColorAttachment colorAttachment{};
                colorAttachment.view = beginCmd.colorAttachments[ca0].view.Get();

                beginCmd.colorAttachments[ca0].clearColor = colorAttachment.clearValue = {
                    dClearColor, dClearColor, dClearColor, dClearColor};
                beginCmd.colorAttachments[ca0].loadOp = colorAttachment.loadOp =
                    wgpu::LoadOp::Clear;
                beginCmd.colorAttachments[ca0].storeOp = colorAttachment.storeOp =
                    wgpu::StoreOp::Store;

                RenderPassDescriptor passDesc{};
                passDesc.colorAttachments = SpanFromRef<ColorAttachmentIndex>(colorAttachment);

                for (uint32_t depthSlice = 0; depthSlice < depthSliceCount; ++depthSlice) {
                    beginCmd.colorAttachments[ca0].depthSlice = colorAttachment.depthSlice =
                        depthSlice;

                    beginCmd.attachmentState =
                        device->GetOrCreateAttachmentState(Unpack(&passDesc));

                    DAWN_TRY(
                        RecordBeginRenderPass(recordingContext, ToBackend(GetDevice()), &beginCmd));
                    RecordEndRenderPass(recordingContext, ToBackend(GetDevice()));
                }
            }
        }
    } else if (GetFormat().HasDepthOrStencil()) {
        TransitionUsageNow(recordingContext, wgpu::TextureUsage::CopyDst, wgpu::ShaderStage::None,
                           range);

        for (uint32_t level = range.baseMipLevel; level < range.baseMipLevel + range.levelCount;
             ++level) {
            imageRange.baseMipLevel = level;
            for (uint32_t layer = range.baseArrayLayer;
                 layer < range.baseArrayLayer + range.layerCount; ++layer) {
                Aspect aspects = Aspect::None;
                for (Aspect aspect : IterateEnumMask(range.aspects)) {
                    if (clearValue == TextureBase::ClearValue::Zero &&
                        IsSubresourceContentInitialized(
                            SubresourceRange::SingleMipAndLayer(level, layer, aspect))) {
                        // Skip lazy clears if already initialized.
                        continue;
                    }
                    aspects |= aspect;
                }

                if (aspects == Aspect::None) {
                    continue;
                }

                imageRange.aspectMask = VulkanAspectMask(aspects);
                imageRange.baseMipLevel = level;
                imageRange.baseArrayLayer = layer;

                VkClearDepthStencilValue clearDepthStencilValue[1];
                clearDepthStencilValue[0].depth = fClearColor;
                clearDepthStencilValue[0].stencil = uClearColor;
                device->fn.CmdClearDepthStencilImage(recordingContext->commandBuffer, GetHandle(),
                                                     VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
                                                     clearDepthStencilValue, 1, &imageRange);
            }
        }
    } else {
        if (range.aspects == Aspect::None) {
            return {};
        }

        TransitionUsageNow(recordingContext, wgpu::TextureUsage::CopyDst, wgpu::ShaderStage::None,
                           range);

        // need to clear the texture with a copy from buffer
        DAWN_ASSERT(range.aspects == Aspect::Color || range.aspects == Aspect::Plane0 ||
                    range.aspects == Aspect::Plane1 || range.aspects == Aspect::Plane2);
        const TypedTexelBlockInfo& blockInfo = GetFormat().GetAspectInfo(range.aspects).block;

        BlockExtent3D largestMipSize = blockInfo.ToBlock(
            GetMipLevelSingleSubresourcePhysicalSize(range.baseMipLevel, range.aspects));

        uint64_t bytesPerRow = Align(blockInfo.ToBytes(largestMipSize.width),
                                     device->GetOptimalBytesPerRowAlignment());
        BlockCount blocksPerRow = blockInfo.BytesToBlocks(bytesPerRow);
        BlockCount uploadBlocks =
            blocksPerRow * largestMipSize.height * largestMipSize.depthOrArrayLayers;
        uint64_t uploadSize = blockInfo.ToBytes(uploadBlocks);

        DAWN_UNSAFE_TODO(DAWN_TRY(device->GetDynamicUploader()->WithUploadReservation(
            uploadSize, blockInfo.byteSize, [&](UploadReservation reservation) -> MaybeError {
                memset(reservation.mappedPointer, sign_dcast(uClearColor), uploadSize);

                std::vector<VkBufferImageCopy> regions;
                for (uint32_t level = range.baseMipLevel;
                     level < range.baseMipLevel + range.levelCount; ++level) {
                    BlockExtent3D copySize = blockInfo.ToBlock(
                        GetMipLevelSingleSubresourcePhysicalSize(level, range.aspects));
                    imageRange.baseMipLevel = level;
                    for (uint32_t layer = range.baseArrayLayer;
                         layer < range.baseArrayLayer + range.layerCount; ++layer) {
                        if (clearValue == TextureBase::ClearValue::Zero &&
                            IsSubresourceContentInitialized(
                                SubresourceRange::SingleMipAndLayer(level, layer, range.aspects))) {
                            // Skip lazy clears if already initialized.
                            continue;
                        }

                        BufferCopy bufferCopy;
                        bufferCopy.offset = reservation.offsetInBuffer;
                        bufferCopy.blocksPerRow = blocksPerRow;
                        bufferCopy.rowsPerImage = copySize.height;

                        TextureCopy textureCopy;
                        textureCopy.aspect = range.aspects;
                        textureCopy.mipLevel = level;
                        textureCopy.origin = {TexelCount{0u}, TexelCount{0u}, TexelCount{layer}};
                        textureCopy.texture = this;

                        regions.push_back(
                            ComputeBufferImageCopyRegion(bufferCopy, textureCopy, copySize));
                    }
                }

                device->fn.CmdCopyBufferToImage(recordingContext->commandBuffer,
                                                ToBackend(reservation.buffer)->GetHandle(),
                                                GetHandle(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
                                                regions.size(), regions.data());
                return {};
            })));
    }

    if (clearValue == TextureBase::ClearValue::Zero) {
        SetIsSubresourceContentInitialized(true, range);
        device->IncrementLazyClearCountForTesting();
    }
    return {};
}



MaybeError Texture::EnsureSubresourceContentInitialized(CommandRecordingContext* recordingContext,
                                                        const SubresourceRange& range) {
    if (!GetDevice()->IsToggleEnabled(Toggle::LazyClearResourceOnFirstUse)) {
        return {};
    }
    if (!IsSubresourceContentInitialized(range)) {
        // If subresource has not been initialized, clear it to black as it could contain dirty
        // bits from recycled memory
        DAWN_TRY(ClearTexture(recordingContext, range, TextureBase::ClearValue::Zero));
    }
    return {};
}

VkImageLayout Texture::GetCurrentLayout(Aspect aspect,
                                        uint32_t arrayLayer,
                                        uint32_t mipLevel) const {
    DAWN_ASSERT(GetFormat().aspects == Aspect::Color);
    return VulkanImageLayout(mSubresourceLastSyncInfos.Get(aspect, arrayLayer, mipLevel).usage);
}

bool Texture::UseCombinedAspects() const {
    return mCombinedAspect != Aspect::None;
}

Aspect Texture::GetDisjointVulkanAspects() const {
    if (UseCombinedAspects()) {
        return mCombinedAspect;
    }
    return GetFormat().aspects;
}

void Texture::TweakTransition(CommandRecordingContext* recordingContext,
                              std::vector<VkImageMemoryBarrier>* barriers,
                              size_t transitionBarrierStart) {}

MaybeError Texture::OnBeforeSubmit(CommandRecordingContext*) {
    DAWN_UNREACHABLE();
}
MaybeError Texture::OnAfterSubmit() {
    DAWN_UNREACHABLE();
}

//
// InternalTexture
//

// static
ResultOrError<Ref<InternalTexture>> InternalTexture::Create(
    Device* device,
    const UnpackedPtr<TextureDescriptor>& descriptor,
    VkImageUsageFlags extraUsages) {
    Ref<InternalTexture> texture = AcquireRef(new InternalTexture(device, descriptor));
    DAWN_TRY(texture->Initialize(extraUsages));
    return std::move(texture);
}

MaybeError InternalTexture::Initialize(VkImageUsageFlags extraUsages) {
    Device* device = ToBackend(GetDevice());

    // If this triggers, it means it's time to add tests and implement support for readonly
    // depth-stencil attachments that are also used as readonly storage bindings in the pass.
    // Have fun! :)
    DAWN_ASSERT(
        !(GetFormat().HasDepthOrStencil() && (GetUsage() & wgpu::TextureUsage::StorageBinding)));

    // Create the Vulkan image "container". We don't need to check that the format supports the
    // combination of sample, usage etc. because validation should have been done in the Dawn
    // frontend already based on the minimum supported formats in the Vulkan spec
    VkImageCreateInfo createInfo = {};
    FillVulkanCreateInfoSizesAndType(*this, &createInfo);
    createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
    createInfo.format = VulkanImageFormat(device, GetFormat().format);
    createInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
    createInfo.usage = VulkanImageUsage(device, GetInternalUsage(), GetFormat()) | extraUsages;
    createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
    createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
    createInfo.flags =
        VulkanImageCreateFlags(device, GetInternalUsage(), GetFormat(), GetSampleCount());

    std::vector<VkFormat> viewFormats;
    bool requiresViewFormatsList = GetViewFormats().any();
    // As current SPIR-V SPEC doesn't support 'bgra8' as a valid image format, to support the
    // STORAGE usage of BGRA8Unorm we have to create an RGBA8Unorm image view on the BGRA8Unorm
    // storage texture and polyfill it as RGBA8Unorm in Tint. See http://crbug.com/dawn/1641 for
    // more details.
    if (createInfo.format == VK_FORMAT_B8G8R8A8_UNORM &&
        createInfo.usage & VK_IMAGE_USAGE_STORAGE_BIT) {
        viewFormats.push_back(VK_FORMAT_R8G8B8A8_UNORM);
        requiresViewFormatsList = true;
    }
    if (GetFormat().IsMultiPlanar() || requiresViewFormatsList) {
        // Multi-planar image needs to have VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT in order to be able
        // to create per-plane view. See
        // https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkImageCreateFlagBits.html
        //
        // Note: we cannot include R8 & RG8 in the viewFormats list of
        // G8_B8R8_2PLANE_420_UNORM. The Vulkan validation layer will disallow that.
        createInfo.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
    }

    // Add the view format list only when the usage does not have storage. Otherwise, the VVL will
    // say creation of the texture is invalid.
    // See https://github.com/gpuweb/gpuweb/issues/4426.
    VkImageFormatListCreateInfo imageFormatListInfo = {};
    PNextChainBuilder createInfoChain(&createInfo);
    if (requiresViewFormatsList && device->GetDeviceInfo().HasExt(DeviceExt::ImageFormatList) &&
        !(createInfo.usage & VK_IMAGE_USAGE_STORAGE_BIT)) {
        createInfoChain.Add(&imageFormatListInfo, VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO);
        viewFormats.push_back(VulkanImageFormat(device, GetFormat().format));
        for (FormatIndex i : GetViewFormats()) {
            const Format& viewFormat = device->GetValidInternalFormat(i);
            viewFormats.push_back(VulkanImageFormat(device, viewFormat.format));
        }

        imageFormatListInfo.viewFormatCount = viewFormats.size();
        imageFormatListInfo.pViewFormats = viewFormats.data();
    }

    DAWN_ASSERT(IsSampleCountSupported(device, createInfo));

    if (GetArrayLayers() >= 6 && GetBaseSize().width == GetBaseSize().height) {
        createInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
    }

    if (createInfo.imageType == VK_IMAGE_TYPE_3D &&
        createInfo.usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
        createInfo.flags |= VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
    }

    // Zero initialization and various workarounds need to copy to the images. Always add
    // VK_IMAGE_USAGE_TRANSFER_DST_BIT to allow for these use cases, unless the image is a transient
    // attachment and incompatible with transfers.
    if (!(GetInternalUsage() & wgpu::TextureUsage::TransientAttachment)) {
        createInfo.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
    }

    DAWN_TRY(CheckVkOOMThenSuccess(
        device->fn.CreateImage(device->GetVkDevice(), &createInfo, nullptr, &*mHandle),
        "CreateImage"));

    // Create the image memory and associate it with the container
    VkMemoryRequirements requirements;
    device->fn.GetImageMemoryRequirements(device->GetVkDevice(), mHandle, &requirements);

    bool forceDisableSubAllocation =
        (device->IsToggleEnabled(
            Toggle::DisableSubAllocationFor2DTextureWithCopyDstOrRenderAttachment)) &&
        GetDimension() == wgpu::TextureDimension::e2D &&
        (GetInternalUsage() & (wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::RenderAttachment));
    auto memoryKind = (GetInternalUsage() & wgpu::TextureUsage::TransientAttachment)
                          ? MemoryKind::LazilyAllocated
                          : MemoryKind::DeviceLocal;
    DAWN_TRY_ASSIGN(mMemoryAllocation, device->GetResourceMemoryAllocator()->Allocate(
                                           requirements, memoryKind, forceDisableSubAllocation));

    DAWN_TRY(CheckVkSuccess(
        device->fn.BindImageMemory(device->GetVkDevice(), mHandle,
                                   ToBackend(mMemoryAllocation.GetResourceHeap())->GetMemory(),
                                   mMemoryAllocation.GetOffset()),
        "BindImageMemory"));

    // crbug.com/1361662
    // This works around an Intel Gen12 Mesa bug due to CCS ambiguates stomping on each other.
    // https://gitlab.freedesktop.org/mesa/mesa/-/issues/7301#note_1826367
    if (device->IsToggleEnabled(Toggle::VulkanClearGen12TextureWithCCSAmbiguateOnCreation)) {
        auto format = GetFormat().format;
        bool textureIsBuggy =
            format == wgpu::TextureFormat::R8Unorm || format == wgpu::TextureFormat::R8Snorm ||
            format == wgpu::TextureFormat::R8Uint || format == wgpu::TextureFormat::R8Sint ||
            // These are flaky.
            format == wgpu::TextureFormat::RG16Sint || format == wgpu::TextureFormat::RGBA16Sint ||
            format == wgpu::TextureFormat::RGBA32Float;
        textureIsBuggy &= GetNumMipLevels() > 1;
        textureIsBuggy &= GetDimension() == wgpu::TextureDimension::e2D;
        textureIsBuggy &= IsPowerOfTwo(GetBaseSize().width) && IsPowerOfTwo(GetBaseSize().height);
        if (textureIsBuggy) {
            DAWN_TRY(ClearTexture(ToBackend(GetDevice()->GetQueue())->GetPendingRecordingContext(),
                                  GetAllSubresources(), TextureBase::ClearValue::Zero));
        }
    }

    if (device->IsToggleEnabled(Toggle::NonzeroClearResourcesOnCreationForTesting)) {
        DAWN_TRY(ClearTexture(ToBackend(GetDevice()->GetQueue())->GetPendingRecordingContext(),
                              GetAllSubresources(), TextureBase::ClearValue::NonZero));
    }

    SetLabelImpl();

    return {};
}

void InternalTexture::DestroyImpl(DestroyReason reason) {
    // TODO(crbug.com/dawn/831): DestroyImpl is called from two places.
    // - It may be called if the texture is explicitly destroyed with APIDestroy.
    //   This case is NOT thread-safe and needs proper synchronization with other
    //   simultaneous uses of the texture.
    // - It may be called when the last ref to the texture is dropped and the texture
    //   is implicitly destroyed. This case is thread-safe because there are no
    //   other threads using the texture since there are no other live refs.
    Device* device = ToBackend(GetDevice());

    device->GetFencedDeleter()->DeleteWhenUnused(mHandle);
    mHandle = VK_NULL_HANDLE;

    device->GetResourceMemoryAllocator()->Deallocate(&mMemoryAllocation);
    mMemoryAllocation = ResourceMemoryAllocation();

    Texture::DestroyImpl(reason);
}

//
// SwapChainTexture
//

// static
Ref<SwapChainTexture> SwapChainTexture::Create(Device* device,
                                               const UnpackedPtr<TextureDescriptor>& descriptor,
                                               VkImage nativeImage) {
    Ref<SwapChainTexture> texture = AcquireRef(new SwapChainTexture(device, descriptor));
    texture->Initialize(nativeImage);
    return texture;
}

void SwapChainTexture::Initialize(VkImage nativeImage) {
    mHandle = nativeImage;
    mSubresourceLastSyncInfos.Fill({kPresentAcquireTextureUsage, wgpu::ShaderStage::None});
    SetLabelHelper("Dawn_SwapChainTexture");
}

//
// ImportedTextureBase
//

ImportedTextureBase::~ImportedTextureBase() {
    // The external semaphore can be queried even after device loss or destroy (so applications can
    // keep relying on them for synchronization) so only destroy it in the destructor instead of
    // DestroyImpl.
    if (mExternalSemaphoreHandle != kNullExternalSemaphoreHandle) {
        ToBackend(GetDevice())
            ->GetExternalSemaphoreService()
            ->CloseHandle(mExternalSemaphoreHandle);
        mExternalSemaphoreHandle = kNullExternalSemaphoreHandle;
    }
}

void ImportedTextureBase::DestroyImpl(DestroyReason reason) {
    // TODO(crbug.com/dawn/831): DestroyImpl is called from two places.
    // - It may be called if the texture is explicitly destroyed with APIDestroy.
    //   This case is NOT thread-safe and needs proper synchronization with other
    //   simultaneous uses of the texture.
    // - It may be called when the last ref to the texture is dropped and the texture
    //   is implicitly destroyed. This case is thread-safe because there are no
    //   other threads using the texture since there are no other live refs.
    if (mPendingSemaphore != VK_NULL_HANDLE) {
        ToBackend(GetDevice())->GetFencedDeleter()->DeleteWhenUnused(mPendingSemaphore);
        mPendingSemaphore = VK_NULL_HANDLE;
    }
    Texture::DestroyImpl(reason);
}

void ImportedTextureBase::TransitionEagerlyForExport(CommandRecordingContext* recordingContext) {
    mExternalState = ExternalState::EagerlyTransitioned;

    // Get any usage, ideally the last one to do nothing
    DAWN_ASSERT(GetNumMipLevels() == 1 && GetArrayLayers() == 1);
    const SubresourceRange range = {GetDisjointVulkanAspects(), {0, 1}, {0, 1}};
    const TextureSyncInfo syncInfo = mSubresourceLastSyncInfos.Get(range.aspects, 0, 0);

    std::vector<VkImageMemoryBarrier> barriers;
    VkPipelineStageFlags srcStages = 0;
    VkPipelineStageFlags dstStages = 0;

    // Same usage as last.
    TransitionUsageAndGetResourceBarrier(syncInfo.usage, syncInfo.shaderStages, range, &barriers,
                                         &srcStages, &dstStages);

    DAWN_ASSERT(barriers.size() == 1);
    VkImageMemoryBarrier& barrier = barriers[0];
    // The barrier must be paired with another barrier that will specify the dst access mask on the
    // importing queue.
    barrier.dstAccessMask = 0;

    if (mDesiredExportLayout != VK_IMAGE_LAYOUT_UNDEFINED) {
        barrier.newLayout = mDesiredExportLayout;
    }

    Device* device = ToBackend(GetDevice());
    barrier.srcQueueFamilyIndex = device->GetGraphicsQueueFamily();
    barrier.dstQueueFamilyIndex = mExportQueueFamilyIndex;

    // We don't know when the importing queue will need the texture, so pass
    // VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT to ensure the barrier happens-before any usage in the
    // importing queue.
    dstStages = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;

    device->fn.CmdPipelineBarrier(recordingContext->commandBuffer, srcStages, dstStages, 0, 0,
                                  nullptr, 0, nullptr, 1, &barrier);
}

bool ImportedTextureBase::CanReuseWithoutBarrier(wgpu::TextureUsage lastUsage,
                                                 wgpu::TextureUsage usage,
                                                 wgpu::ShaderStage lastShaderStage,
                                                 wgpu::ShaderStage shaderStage) {
    return mLastExternalState == mExternalState &&
           Texture::CanReuseWithoutBarrier(lastUsage, usage, lastShaderStage, shaderStage);
}

void ImportedTextureBase::TweakTransition(CommandRecordingContext* recordingContext,
                                          std::vector<VkImageMemoryBarrier>* barriers,
                                          size_t transitionBarrierStart) {
    DAWN_ASSERT(GetNumMipLevels() == 1 && GetArrayLayers() == 1);

    mLastSharedTextureMemoryUsageSerial = GetDevice()->GetQueue()->GetPendingCommandSerial();

    // transitionBarrierStart specify the index where barriers for current transition start in
    // the vector. barriers->size() - transitionBarrierStart is the number of barriers that we
    // have already added into the vector during current transition.
    DAWN_ASSERT(barriers->size() - transitionBarrierStart <= 1);

    if (mExternalState == ExternalState::PendingAcquire ||
        mExternalState == ExternalState::EagerlyTransitioned) {
        recordingContext->specialSyncTextures.insert(this);
        if (barriers->size() == transitionBarrierStart) {
            barriers->push_back(BuildMemoryBarrier(
                this, wgpu::TextureUsage::None, wgpu::TextureUsage::None,
                SubresourceRange::SingleMipAndLayer(0, 0, GetDisjointVulkanAspects())));
        }

        VkImageMemoryBarrier* barrier = &(*barriers)[transitionBarrierStart];
        // Transfer texture from external queue to graphics queue
        barrier->srcQueueFamilyIndex = mExportQueueFamilyIndex;
        barrier->dstQueueFamilyIndex = ToBackend(GetDevice())->GetGraphicsQueueFamily();

        // srcAccessMask means nothing when importing. Queue transfers require a barrier on
        // both the importing and exporting queues. The exporting queue should have specified
        // this.
        barrier->srcAccessMask = 0;

        // Save the desired layout. We may need to transition through an intermediate
        // |mPendingAcquireLayout| first.
        VkImageLayout desiredLayout = barrier->newLayout;

        if (mExternalState == ExternalState::PendingAcquire) {
            bool isInitialized = IsSubresourceContentInitialized(GetAllSubresources());

            // We don't care about the pending old layout if the texture is uninitialized. The
            // driver is free to discard it. Also it is invalid to transition to layout UNDEFINED or
            // PREINITIALIZED. If the embedder provided no new layout, or we don't care about the
            // previous contents, we can skip the layout transition.
            // https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-VkImageMemoryBarrier-newLayout-01198
            if (!isInitialized || mPendingAcquireNewLayout == VK_IMAGE_LAYOUT_UNDEFINED ||
                mPendingAcquireNewLayout == VK_IMAGE_LAYOUT_PREINITIALIZED) {
                barrier->oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
                barrier->newLayout = desiredLayout;
            } else {
                barrier->oldLayout = mPendingAcquireOldLayout;
                barrier->newLayout = mPendingAcquireNewLayout;
            }
        } else {
            // In case of ExternalState::EagerlyTransitioned, the layouts of the texture's queue
            // release were always same. So we exactly match that here for the queue acquire.
            // The spec text:
            // If the transfer is via an image memory barrier, and an image layout transition is
            // desired, then the values of oldLayout and newLayout in the release operation's memory
            // barrier must be equal to values of oldLayout and newLayout in the acquire operation's
            // memory barrier.
            barrier->newLayout = barrier->oldLayout;
        }

        // If these are unequal, we need an another barrier to transition the layout.
        if (barrier->newLayout != desiredLayout) {
            VkImageMemoryBarrier layoutBarrier;
            layoutBarrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
            layoutBarrier.pNext = nullptr;
            layoutBarrier.image = GetHandle();
            layoutBarrier.subresourceRange = barrier->subresourceRange;

            // Transition from the acquired new layout to the desired layout.
            layoutBarrier.oldLayout = barrier->newLayout;
            layoutBarrier.newLayout = desiredLayout;

            layoutBarrier.srcAccessMask = 0;
            layoutBarrier.dstAccessMask = barrier->dstAccessMask;
            layoutBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
            layoutBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;

            barriers->push_back(layoutBarrier);
        }

        mExternalState = ExternalState::Acquired;
    }

    mLastExternalState = mExternalState;
}

MaybeError ImportedTextureBase::EndAccess(ExternalSemaphoreHandle* handle,
                                          VkImageLayout* releasedOldLayout,
                                          VkImageLayout* releasedNewLayout) {
    DAWN_ASSERT(GetNumMipLevels() == 1 && GetArrayLayers() == 1);

    // Release the texture
    mExternalState = ExternalState::Released;

    // Compute the layouts for the queue transition for export. desiredLayout == UNDEFINED is a tag
    // value used to export with whatever the current layout is. However queue transitioning to the
    // UNDEFINED layout is disallowed so we handle the case where currentLayout is UNDEFINED by
    // promoting to GENERAL.
    VkImageLayout currentLayout = GetCurrentLayout(GetDisjointVulkanAspects());
    VkImageLayout targetLayout;
    if (currentLayout != VK_IMAGE_LAYOUT_UNDEFINED) {
        targetLayout = currentLayout;
    } else {
        targetLayout = VK_IMAGE_LAYOUT_GENERAL;
    }

    // We have to manually trigger a transition if the texture hasn't been actually used or if we
    // need a layout transition.
    // TODO(dawn:1509): Avoid the empty submit.
    if (mExternalSemaphoreHandle == kNullExternalSemaphoreHandle || targetLayout != currentLayout) {
        mDesiredExportLayout = targetLayout;

        Queue* queue = ToBackend(GetDevice()->GetQueue());
        CommandRecordingContext* recordingContext = queue->GetPendingRecordingContext();
        recordingContext->specialSyncTextures.insert(this);
        DAWN_TRY(queue->SubmitPendingCommands());

        currentLayout = targetLayout;
    }
    DAWN_ASSERT(mExternalSemaphoreHandle != kNullExternalSemaphoreHandle);

    // Write out the layouts and signal semaphore
    *releasedOldLayout = currentLayout;
    *releasedNewLayout = targetLayout;
    *handle = mExternalSemaphoreHandle;
    mExternalSemaphoreHandle = kNullExternalSemaphoreHandle;
    return {};
}

MaybeError ImportedTextureBase::OnBeforeSubmit(CommandRecordingContext* context) {
    // On every submit using an exportable texture, we eagerly prepare for an export. This avoids
    // the need to schedule an almost empty submit just for exporting later. To export we both need
    // to transition the resource to export it, and need an exportable semaphore for future
    // synchronization.
    TransitionEagerlyForExport(context);

    // Create the external semaphore and add it to be signaled, but only mark it pending: if
    // anything fails during the submit we still keep the previously signaled exportable semaphore.
    // Note that VUID-VkSemaphoreGetFdInfoKHR-handleType-01135 requires that only signaled
    // semaphores be exported, so the export must be done in OnAfterSubmit.
    auto semaphoreService = ToBackend(GetDevice())->GetExternalSemaphoreService();
    DAWN_TRY_ASSIGN(mPendingSemaphore, semaphoreService->CreateExportableSemaphore());
    context->signalSemaphores.push_back(mPendingSemaphore);

    return {};
}

MaybeError ImportedTextureBase::OnAfterSubmit() {
    Device* device = ToBackend(GetDevice());

    // The submit succeeded, we can replace the previous external semaphore with the pending one.
    if (mExternalSemaphoreHandle != kNullExternalSemaphoreHandle) {
        device->GetExternalSemaphoreService()->CloseHandle(mExternalSemaphoreHandle);
        // Set the handle to null after it's been closed so that we don't accidentally attempt to
        // use or close it again if the ExportSemaphore() below fails.
        mExternalSemaphoreHandle = kNullExternalSemaphoreHandle;
    }

    DAWN_TRY_ASSIGN(mExternalSemaphoreHandle,
                    device->GetExternalSemaphoreService()->ExportSemaphore(mPendingSemaphore));
    ToBackend(GetDevice())->GetFencedDeleter()->DeleteWhenUnused(mPendingSemaphore);
    mPendingSemaphore = VK_NULL_HANDLE;

    return {};
}

//
// ExternalVkImageTexture
//

// static
ResultOrError<Ref<ExternalVkImageTexture>> ExternalVkImageTexture::Create(
    Device* device,
    const ExternalImageDescriptorVk* descriptor,
    const UnpackedPtr<TextureDescriptor>& textureDescriptor,
    external_memory::Service* externalMemoryService) {
    Ref<ExternalVkImageTexture> texture =
        AcquireRef(new ExternalVkImageTexture(device, textureDescriptor));
    DAWN_TRY(texture->Initialize(descriptor, externalMemoryService));
    return texture;
}

void ExternalVkImageTexture::DestroyImpl(DestroyReason reason) {
    // TODO(crbug.com/dawn/831): DestroyImpl is called from two places.
    // - It may be called if the texture is explicitly destroyed with APIDestroy.
    //   This case is NOT thread-safe and needs proper synchronization with other
    //   simultaneous uses of the texture.
    // - It may be called when the last ref to the texture is dropped and the texture
    //   is implicitly destroyed. This case is thread-safe because there are no
    //   other threads using the texture since there are no other live refs.
    Device* device = ToBackend(GetDevice());

    device->GetFencedDeleter()->DeleteWhenUnused(mHandle);
    mHandle = VK_NULL_HANDLE;

    if (mExternalAllocation != VK_NULL_HANDLE) {
        device->GetFencedDeleter()->DeleteWhenUnused(mExternalAllocation);
        mExternalAllocation = VK_NULL_HANDLE;
    }

    ImportedTextureBase::DestroyImpl(reason);
}

MaybeError ExternalVkImageTexture::Initialize(const ExternalImageDescriptorVk* descriptor,
                                              external_memory::Service* externalMemoryService) {
    Device* device = ToBackend(GetDevice());
    VkFormat format = VulkanImageFormat(device, GetFormat().format);
    VkImageUsageFlags usage = VulkanImageUsage(device, GetInternalUsage(), GetFormat());

    [[maybe_unused]] bool supportsDisjoint;
    DAWN_INVALID_IF(
        !externalMemoryService->SupportsCreateImage(descriptor, format, usage, &supportsDisjoint),
        "Creating an image from external memory is not supported.");
    // The creation of mSubresourceLastUsage assumes that multi-planar are always disjoint and sets
    // the combined aspect without checking for disjoint support.
    // TODO(dawn:1548): Support multi-planar images with the DISJOINT feature and potentially allow
    // acting on planes individually? Always using Color is valid even for disjoint images.
    DAWN_ASSERT(!GetFormat().IsMultiPlanar() || mCombinedAspect == Aspect::Color);

    mExternalState = ExternalState::PendingAcquire;
    mLastExternalState = ExternalState::Released;
    mExportQueueFamilyIndex = externalMemoryService->GetQueueFamilyIndex(descriptor->GetType());

    mPendingAcquireOldLayout = descriptor->releasedOldLayout;
    mPendingAcquireNewLayout = descriptor->releasedNewLayout;

    VkImageCreateInfo baseCreateInfo = {};
    FillVulkanCreateInfoSizesAndType(*this, &baseCreateInfo);
    baseCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
    baseCreateInfo.format = format;
    baseCreateInfo.usage = usage;
    baseCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
    baseCreateInfo.queueFamilyIndexCount = 0;
    baseCreateInfo.pQueueFamilyIndices = nullptr;

    // Zero initialization and various workarounds need to copy to the images. Always add
    // VK_IMAGE_USAGE_TRANSFER_DST_BIT to allow for these use cases, unless the image is a transient
    // attachment and incompatible with transfers.
    if (!(GetInternalUsage() & wgpu::TextureUsage::TransientAttachment)) {
        baseCreateInfo.usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
    }

    VkImageFormatListCreateInfo imageFormatListInfo = {};
    PNextChainBuilder createInfoChain(&baseCreateInfo);
    std::vector<VkFormat> viewFormats;
    if (GetViewFormats().any()) {
        baseCreateInfo.flags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
        if (device->GetDeviceInfo().HasExt(DeviceExt::ImageFormatList)) {
            createInfoChain.Add(&imageFormatListInfo,
                                VK_STRUCTURE_TYPE_IMAGE_FORMAT_LIST_CREATE_INFO);
            for (FormatIndex i : GetViewFormats()) {
                const Format& viewFormat = device->GetValidInternalFormat(i);
                viewFormats.push_back(VulkanImageFormat(device, viewFormat.format));
            }

            imageFormatListInfo.viewFormatCount = viewFormats.size();
            imageFormatListInfo.pViewFormats = viewFormats.data();
        }
    }

    DAWN_TRY_ASSIGN(mHandle, externalMemoryService->CreateImage(descriptor, baseCreateInfo));
    SetLabelHelper("Dawn_ExternalVkImageTexture");

    return {};
}

MaybeError ExternalVkImageTexture::BindExternalMemory(const ExternalImageDescriptorVk* descriptor,
                                                      VkDeviceMemory externalMemoryAllocation,
                                                      std::vector<VkSemaphore> waitSemaphores) {
    Device* device = ToBackend(GetDevice());
    DAWN_TRY(CheckVkSuccess(
        device->fn.BindImageMemory(device->GetVkDevice(), mHandle, externalMemoryAllocation, 0),
        "BindImageMemory (external)"));

    // Don't clear imported texture if already initialized
    if (descriptor->isInitialized) {
        SetIsSubresourceContentInitialized(true, GetAllSubresources());
    }

    // Success, acquire all the external objects.
    mExternalAllocation = externalMemoryAllocation;
    mWaitRequirements = std::move(waitSemaphores);
    return {};
}

MaybeError ExternalVkImageTexture::ExportExternalTexture(VkImageLayout desiredLayout,
                                                         ExternalSemaphoreHandle* handle,
                                                         VkImageLayout* releasedOldLayout,
                                                         VkImageLayout* releasedNewLayout) {
    DAWN_INVALID_IF(mExternalState == ExternalState::Released,
                    "Can't export a signal semaphore from signaled texture %s.", this);

    DAWN_INVALID_IF(mExternalAllocation == VK_NULL_HANDLE,
                    "Can't export a signal semaphore from destroyed or non-external texture %s.",
                    this);

    DAWN_INVALID_IF(desiredLayout != VK_IMAGE_LAYOUT_UNDEFINED,
                    "desiredLayout (%d) was not VK_IMAGE_LAYOUT_UNDEFINED", desiredLayout);

    DAWN_TRY(EndAccess(handle, releasedOldLayout, releasedNewLayout));

    // Destroy the texture so it can't be used again
    Destroy();
    return {};
}

MaybeError ExternalVkImageTexture::OnBeforeSubmit(CommandRecordingContext* context) {
    context->waitSemaphores.insert(context->waitSemaphores.end(), mWaitRequirements.begin(),
                                   mWaitRequirements.end());
    mWaitRequirements.clear();
    return ImportedTextureBase::OnBeforeSubmit(context);
}

//
// SharedTexture
//

// static
ResultOrError<Ref<SharedTexture>> SharedTexture::Create(
    SharedTextureMemory* memory,
    const UnpackedPtr<TextureDescriptor>& textureDescriptor) {
    Ref<SharedTexture> texture =
        AcquireRef(new SharedTexture(ToBackend(memory->GetDevice()), textureDescriptor));
    texture->Initialize(memory);
    return texture;
}

void SharedTexture::DestroyImpl(DestroyReason reason) {
    // TODO(crbug.com/dawn/831): DestroyImpl is called from two places.
    // - It may be called if the texture is explicitly destroyed with APIDestroy.
    //   This case is NOT thread-safe and needs proper synchronization with other
    //   simultaneous uses of the texture.
    // - It may be called when the last ref to the texture is dropped and the texture
    //   is implicitly destroyed. This case is thread-safe because there are no
    //   other threads using the texture since there are no other live refs.
    mSharedTextureMemoryObjects = {};

    ImportedTextureBase::DestroyImpl(reason);
}

void SharedTexture::Initialize(SharedTextureMemory* memory) {
    mSharedResourceMemoryContents = memory->GetContents();
    mSharedTextureMemoryObjects = {memory->GetVkImage(), memory->GetVkDeviceMemory()};
    mHandle = mSharedTextureMemoryObjects.vkImage->Get();
    mExportQueueFamilyIndex = memory->GetQueueFamilyIndex();
}

void SharedTexture::SetPendingAcquire(VkImageLayout pendingAcquireOldLayout,
                                      VkImageLayout pendingAcquireNewLayout) {
    DAWN_ASSERT(GetSharedResourceMemoryContents() != nullptr);
    mExternalState = ExternalState::PendingAcquire;
    mLastExternalState = ExternalState::PendingAcquire;

    mPendingAcquireOldLayout = pendingAcquireOldLayout;
    mPendingAcquireNewLayout = pendingAcquireNewLayout;
}

MaybeError SharedTexture::OnBeforeSubmit(CommandRecordingContext* context) {
    Device* device = ToBackend(GetDevice());
    SharedResourceMemoryContents* contents = GetSharedResourceMemoryContents();

    SharedTextureMemoryBase::PendingFenceList fences;
    contents->AcquirePendingFences(&fences);

    for (const auto& fence : fences) {
        // All semaphores are binary semaphores.
        DAWN_ASSERT(fence.signaledValue == 1u);
        ExternalSemaphoreHandle semaphoreHandle = ToBackend(fence.object)->GetHandle().Get();

        VkSemaphore semaphore;
        DAWN_TRY_ASSIGN(semaphore,
                        device->GetExternalSemaphoreService()->ImportSemaphore(semaphoreHandle));
        context->waitSemaphores.push_back(semaphore);
    }

    return ImportedTextureBase::OnBeforeSubmit(context);
}

//
// TextureView
//

// static
ResultOrError<Ref<TextureView>> TextureView::Create(
    TextureBase* texture,
    uint64_t textureViewId,
    const UnpackedPtr<TextureViewDescriptor>& descriptor) {
    Ref<TextureView> view = AcquireRef(new TextureView(texture, textureViewId, descriptor));
    DAWN_TRY(view->Initialize(descriptor));
    return view;
}

MaybeError TextureView::Initialize(const UnpackedPtr<TextureViewDescriptor>& descriptor) {
    if ((GetInternalUsage() & ~(wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst)) == 0) {
        // If the texture view has no other usage than CopySrc and CopyDst, then it can't
        // actually be used as a render pass attachment or sampled/storage texture. The Vulkan
        // validation errors warn if you create such a vkImageView, so return early.
        return {};
    }

    // Texture could be destroyed by the time we make a view.
    if (GetTexture()->IsDestroyed()) {
        return {};
    }

    Device* device = ToBackend(GetTexture()->GetDevice());
    VkImageViewCreateInfo createInfo = GetCreateInfo(descriptor->format, descriptor->dimension);

    VkImageViewUsageCreateInfo usageInfo = {};
    usageInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO;
    usageInfo.usage = VulkanImageUsage(device, GetInternalUsage(), GetFormat());
    createInfo.pNext = &usageInfo;

    // Compute and link the VkSamplerYCbCrConversion, if any is needed.
    VkSamplerYcbcrConversionInfo samplerYCbCrInfo = {};
    if (GetTexture()->GetFormat().format == wgpu::TextureFormat::OpaqueYCbCrAndroid) {
        auto stmContents = static_cast<SharedTextureMemoryContentsVk*>(
            GetTexture()->GetSharedResourceMemoryContents());
        mIsYCbCrFilterable = stmContents->IsYCbCrFilterable();

        YCbCrVkDescriptor yCbCr;
        if (auto* yCbCrVkDescriptor = descriptor.Get<YCbCrVkDescriptor>()) {
            // The YCbCr conversion can be specified by the user with the YCbCrVulkanSamplers
            // feature.
            DAWN_ASSERT(device->HasFeature(Feature::YCbCrVulkanSamplers));

            yCbCr = yCbCrVkDescriptor->WithTrivialFrontendDefaults();
            yCbCr.nextInChain = nullptr;
        } else {
            // When using OpaqueYCbCrAndroidForExternalTexture, the YCbCr conversion is the same one
            // that's going to be used for the ExternalTexture static samplers.
            // TODO(https://crbug.com/497675620): Specialize the conversion at the same time as all
            // the other state, in order to take advantage of hardware YCbCr to RGB conversion when
            // present.
            DAWN_ASSERT(device->HasFeature(Feature::OpaqueYCbCrAndroidForExternalTexture));

            yCbCr = StaticSamplerSpecialization::GetYCbCrForTextureView(
                static_cast<VkFormat>(stmContents->GetYCbCrVkDesc().vkFormat),
                stmContents->GetYCbCrVkDesc().externalFormat);
        }

        // Create the VkSamplerYCbCrConversion and link it in the createInfo.
        DAWN_TRY_ASSIGN(mSamplerYCbCrConversion, CreateSamplerYCbCrConversion(device, yCbCr));

        samplerYCbCrInfo.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO;
        samplerYCbCrInfo.pNext = nullptr;
        samplerYCbCrInfo.conversion = mSamplerYCbCrConversion;
        createInfo.pNext = &samplerYCbCrInfo;
    } else {
        DAWN_ASSERT(!descriptor.Has<YCbCrVkDescriptor>());
    }

    DAWN_TRY(CheckVkSuccess(
        device->fn.CreateImageView(device->GetVkDevice(), &createInfo, nullptr, &*mHandle),
        "CreateImageView"));

    // We should create an image view with format RGBA8Unorm on the BGRA8Unorm texture when the
    // texture is used as storage texture. See http://crbug.com/dawn/1641 for more details.
    if (createInfo.format == VK_FORMAT_B8G8R8A8_UNORM &&
        (GetTexture()->GetInternalUsage() & wgpu::TextureUsage::StorageBinding)) {
        createInfo.format = VK_FORMAT_R8G8B8A8_UNORM;
        DAWN_TRY(CheckVkSuccess(device->fn.CreateImageView(device->GetVkDevice(), &createInfo,
                                                           nullptr, &*mHandleForBGRA8UnormStorage),
                                "CreateImageView for BGRA8Unorm storage"));
    }

    SetLabelImpl();

    return {};
}

TextureView::TextureView(TextureBase* texture,
                         uint64_t textureViewId,
                         const UnpackedPtr<TextureViewDescriptor>& descriptor)
    : TextureViewBase(texture, descriptor), mTextureViewId(textureViewId) {}
TextureView::~TextureView() {}

void TextureView::DestroyImpl(DestroyReason reason) {
    Device* device = ToBackend(GetTexture()->GetDevice());

    if (mSamplerYCbCrConversion != VK_NULL_HANDLE) {
        device->GetFencedDeleter()->DeleteWhenUnused(mSamplerYCbCrConversion);
        mSamplerYCbCrConversion = VK_NULL_HANDLE;
    }

    if (mHandle != VK_NULL_HANDLE) {
        device->GetFencedDeleter()->DeleteWhenUnused(mHandle);
        mHandle = VK_NULL_HANDLE;
    }

    if (mHandleForBGRA8UnormStorage != VK_NULL_HANDLE) {
        device->GetFencedDeleter()->DeleteWhenUnused(mHandleForBGRA8UnormStorage);
        mHandleForBGRA8UnormStorage = VK_NULL_HANDLE;
    }

    for (auto& handle : mHandlesFor2DViewOn3D) {
        if (handle != VK_NULL_HANDLE) {
            device->GetFencedDeleter()->DeleteWhenUnused(handle);
            handle = VK_NULL_HANDLE;
        }
    }
}

VkImageView TextureView::GetHandle() const {
    return mHandle;
}

VkImageView TextureView::GetHandleForBGRA8UnormStorage() const {
    return mHandleForBGRA8UnormStorage;
}

VkImageViewCreateInfo TextureView::GetCreateInfo(wgpu::TextureFormat format,
                                                 wgpu::TextureViewDimension dimension,
                                                 uint32_t depthSlice) const {
    Device* device = ToBackend(GetTexture()->GetDevice());

    VkImageViewCreateInfo createInfo;
    createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO;
    createInfo.pNext = nullptr;
    createInfo.flags = 0;
    createInfo.image = ToBackend(GetTexture())->GetHandle();
    createInfo.viewType = VulkanImageViewType(dimension);

    const Format& textureFormat = GetTexture()->GetFormat();
    if (textureFormat.HasStencil() &&
        (textureFormat.HasDepth() || !device->IsToggleEnabled(Toggle::VulkanUseS8))) {
        // Unlike multi-planar formats, depth-stencil formats have multiple aspects but are not
        // created with VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT.
        // https://www.khronos.org/registry/vulkan/specs/1.3-extensions/man/html/VkImageViewCreateInfo.html#VUID-VkImageViewCreateInfo-image-01762
        // Without, VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT, the view format must match the texture
        // format.
        createInfo.format = VulkanImageFormat(device, textureFormat.format);
    } else {
        createInfo.format = VulkanImageFormat(device, format);
    }

    bool isDepthOrStencilFormat = GetTexture()->GetFormat().HasDepthOrStencil();
    const wgpu::TextureComponentSwizzle kDefaultSwizzle =
        isDepthOrStencilFormat ? kR001Swizzle : kRGBASwizzle;

    auto swizzle = ComposeSwizzle(kDefaultSwizzle, GetSwizzle());
    if (swizzle == kDefaultSwizzle) {
        // We must use identity swizzle for render views.
        // https://docs.vulkan.org/spec/latest/chapters/renderpass.html#VUID-VkFramebufferCreateInfo-pAttachments-00884
        createInfo.components = VkComponentMapping{VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
                                                   VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
    } else {
        MaybeConvertDepthStencilSwizzleOneToAlpha(isDepthOrStencilFormat, device->GetDeviceInfo(),
                                                  &swizzle);
        createInfo.components = VkComponentMapping{
            VulkanComponentSwizzle(swizzle.r), VulkanComponentSwizzle(swizzle.g),
            VulkanComponentSwizzle(swizzle.b), VulkanComponentSwizzle(swizzle.a)};
    }

    const SubresourceRange& subresources = GetSubresourceRange();
    createInfo.subresourceRange.baseMipLevel = subresources.baseMipLevel;
    createInfo.subresourceRange.levelCount = subresources.levelCount;
    createInfo.subresourceRange.baseArrayLayer = subresources.baseArrayLayer + depthSlice;
    createInfo.subresourceRange.layerCount = subresources.layerCount;
    createInfo.subresourceRange.aspectMask = VulkanAspectMask(subresources.aspects);

    return createInfo;
}

ResultOrError<VkImageView> TextureView::GetOrCreate2DViewOn3D(uint32_t depthSlice) {
    DAWN_ASSERT(GetTexture()->GetDimension() == wgpu::TextureDimension::e3D);
    DAWN_ASSERT(depthSlice < GetSingleSubresourceVirtualSize().depthOrArrayLayers);

    if (mHandlesFor2DViewOn3D.empty()) {
        mHandlesFor2DViewOn3D.resize(GetSingleSubresourceVirtualSize().depthOrArrayLayers);
    }

    if (mHandlesFor2DViewOn3D[depthSlice] != VK_NULL_HANDLE) {
        return static_cast<VkImageView>(mHandlesFor2DViewOn3D[depthSlice]);
    }

    Device* device = ToBackend(GetTexture()->GetDevice());
    VkImageViewCreateInfo createInfo =
        GetCreateInfo(GetFormat().format, wgpu::TextureViewDimension::e2D, depthSlice);

    VkImageView view;
    DAWN_TRY(CheckVkSuccess(
        device->fn.CreateImageView(device->GetVkDevice(), &createInfo, nullptr, &*view),
        "CreateImageView for 2D view on 3D image"));

    mHandlesFor2DViewOn3D[depthSlice] = view;

    return view;
}

bool TextureView::IsYCbCrFilterable() const {
    DAWN_ASSERT(IsYCbCr());
    return mIsYCbCrFilterable;
}

VkImageLayout TextureView::VulkanImageLayout(wgpu::TextureUsage usage) const {
    return dawn::native::vulkan::VulkanImageLayout(GetFormat(), usage, GetUsage());
}

void TextureView::SetLabelImpl() {
    SetDebugName(ToBackend(GetDevice()), mHandle, "Dawn_TextureView", GetLabel());
}

}  // namespace dawn::native::vulkan
