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

#include "dawn/native/vulkan/SwapChainVk.h"

#include <algorithm>
#include <limits>
#include <utility>

#include "dawn/common/Compiler.h"
#include "dawn/native/Instance.h"
#include "dawn/native/Surface.h"
#include "dawn/native/vulkan/AdapterVk.h"
#include "dawn/native/vulkan/BackendVk.h"
#include "dawn/native/vulkan/DeviceVk.h"
#include "dawn/native/vulkan/FencedDeleter.h"
#include "dawn/native/vulkan/TextureVk.h"
#include "dawn/native/vulkan/VulkanError.h"

#if defined(DAWN_USE_X11)
#include "dawn/native/XlibXcbFunctions.h"
#endif  // defined(DAWN_USE_X11)

namespace dawn::native::vulkan {

// OldSwapChain

// static
Ref<OldSwapChain> OldSwapChain::Create(Device* device, const SwapChainDescriptor* descriptor) {
    return AcquireRef(new OldSwapChain(device, descriptor));
}

OldSwapChain::OldSwapChain(Device* device, const SwapChainDescriptor* descriptor)
    : OldSwapChainBase(device, descriptor) {
    const auto& im = GetImplementation();
    DawnWSIContextVulkan wsiContext = {};
    im.Init(im.userData, &wsiContext);

    ASSERT(im.textureUsage != WGPUTextureUsage_None);
    mTextureUsage = static_cast<wgpu::TextureUsage>(im.textureUsage);
}

OldSwapChain::~OldSwapChain() {}

TextureBase* OldSwapChain::GetNextTextureImpl(const TextureDescriptor* descriptor) {
    const auto& im = GetImplementation();
    DawnSwapChainNextTexture next = {};
    DawnSwapChainError error = im.GetNextTexture(im.userData, &next);

    if (error) {
        GetDevice()->HandleError(InternalErrorType::Internal, error);
        return nullptr;
    }

    ::VkImage image = NativeNonDispatachableHandleFromU64<::VkImage>(next.texture.u64);
    VkImage nativeTexture = VkImage::CreateFromHandle(image);
    return Texture::CreateForSwapChain(ToBackend(GetDevice()), descriptor, nativeTexture).Detach();
}

MaybeError OldSwapChain::OnBeforePresent(TextureViewBase* view) {
    Device* device = ToBackend(GetDevice());

    // Perform the necessary pipeline barriers for the texture to be used with the usage
    // requested by the implementation.
    CommandRecordingContext* recordingContext = device->GetPendingRecordingContext();
    ToBackend(view->GetTexture())
        ->TransitionUsageNow(recordingContext, mTextureUsage, view->GetSubresourceRange());

    DAWN_TRY(device->SubmitPendingCommands());

    return {};
}

// SwapChain

namespace {

ResultOrError<VkSurfaceKHR> CreateVulkanSurface(Adapter* adapter, Surface* surface) {
    const VulkanGlobalInfo& info = adapter->GetVulkanInstance()->GetGlobalInfo();
    const VulkanFunctions& fn = adapter->GetVulkanInstance()->GetFunctions();
    VkInstance instance = adapter->GetVulkanInstance()->GetVkInstance();

    // May not be used in the platform-specific switches below.
    DAWN_UNUSED(info);
    DAWN_UNUSED(fn);
    DAWN_UNUSED(instance);

    switch (surface->GetType()) {
#if defined(DAWN_ENABLE_BACKEND_METAL)
        case Surface::Type::MetalLayer:
            if (info.HasExt(InstanceExt::MetalSurface)) {
                VkMetalSurfaceCreateInfoEXT createInfo;
                createInfo.sType = VK_STRUCTURE_TYPE_METAL_SURFACE_CREATE_INFO_EXT;
                createInfo.pNext = nullptr;
                createInfo.flags = 0;
                createInfo.pLayer = surface->GetMetalLayer();

                VkSurfaceKHR vkSurface = VK_NULL_HANDLE;
                DAWN_TRY(CheckVkSuccess(
                    fn.CreateMetalSurfaceEXT(instance, &createInfo, nullptr, &*vkSurface),
                    "CreateMetalSurface"));
                return vkSurface;
            }
            break;
#endif  // defined(DAWN_ENABLE_BACKEND_METAL)

#if DAWN_PLATFORM_IS(WINDOWS)
        case Surface::Type::WindowsHWND:
            if (info.HasExt(InstanceExt::Win32Surface)) {
                VkWin32SurfaceCreateInfoKHR createInfo;
                createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
                createInfo.pNext = nullptr;
                createInfo.flags = 0;
                createInfo.hinstance = static_cast<HINSTANCE>(surface->GetHInstance());
                createInfo.hwnd = static_cast<HWND>(surface->GetHWND());

                VkSurfaceKHR vkSurface = VK_NULL_HANDLE;
                DAWN_TRY(CheckVkSuccess(
                    fn.CreateWin32SurfaceKHR(instance, &createInfo, nullptr, &*vkSurface),
                    "CreateWin32Surface"));
                return vkSurface;
            }
            break;
#endif  // DAWN_PLATFORM_IS(WINDOWS)

#if DAWN_PLATFORM_IS(ANDROID)
        case Surface::Type::AndroidWindow: {
            if (info.HasExt(InstanceExt::AndroidSurface)) {
                ASSERT(surface->GetAndroidNativeWindow() != nullptr);

                VkAndroidSurfaceCreateInfoKHR createInfo;
                createInfo.sType = VK_STRUCTURE_TYPE_ANDROID_SURFACE_CREATE_INFO_KHR;
                createInfo.pNext = nullptr;
                createInfo.flags = 0;
                createInfo.window =
                    static_cast<struct ANativeWindow*>(surface->GetAndroidNativeWindow());

                VkSurfaceKHR vkSurface = VK_NULL_HANDLE;
                DAWN_TRY(CheckVkSuccess(
                    fn.CreateAndroidSurfaceKHR(instance, &createInfo, nullptr, &*vkSurface),
                    "CreateAndroidSurfaceKHR"));
                return vkSurface;
            }

            break;
        }

#endif  // DAWN_PLATFORM_IS(ANDROID)

#if defined(DAWN_USE_WAYLAND)
        case Surface::Type::WaylandSurface: {
            if (info.HasExt(InstanceExt::XlibSurface)) {
                VkWaylandSurfaceCreateInfoKHR createInfo;
                createInfo.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR;
                createInfo.pNext = nullptr;
                createInfo.flags = 0;
                createInfo.display = static_cast<struct wl_display*>(surface->GetWaylandDisplay());
                createInfo.surface = static_cast<struct wl_surface*>(surface->GetWaylandSurface());

                VkSurfaceKHR vkSurface = VK_NULL_HANDLE;
                DAWN_TRY(CheckVkSuccess(
                    fn.CreateWaylandSurfaceKHR(instance, &createInfo, nullptr, &*vkSurface),
                    "CreateWaylandSurface"));
                return vkSurface;
            }
            break;
        }
#endif  // defined(DAWN_USE_WAYLAND)

#if defined(DAWN_USE_X11)
        case Surface::Type::XlibWindow: {
            if (info.HasExt(InstanceExt::XlibSurface)) {
                VkXlibSurfaceCreateInfoKHR createInfo;
                createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
                createInfo.pNext = nullptr;
                createInfo.flags = 0;
                createInfo.dpy = static_cast<Display*>(surface->GetXDisplay());
                createInfo.window = surface->GetXWindow();

                VkSurfaceKHR vkSurface = VK_NULL_HANDLE;
                DAWN_TRY(CheckVkSuccess(
                    fn.CreateXlibSurfaceKHR(instance, &createInfo, nullptr, &*vkSurface),
                    "CreateXlibSurface"));
                return vkSurface;
            }

            // Fall back to using XCB surfaces if the Xlib extension isn't available.
            // See https://xcb.freedesktop.org/MixingCalls/ for more information about
            // interoperability between Xlib and XCB
            const XlibXcbFunctions* xlibXcb = adapter->GetInstance()->GetOrCreateXlibXcbFunctions();
            ASSERT(xlibXcb != nullptr);

            if (info.HasExt(InstanceExt::XcbSurface) && xlibXcb->IsLoaded()) {
                VkXcbSurfaceCreateInfoKHR createInfo;
                createInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
                createInfo.pNext = nullptr;
                createInfo.flags = 0;
                // The XCB connection lives as long as the X11 display.
                createInfo.connection =
                    xlibXcb->xGetXCBConnection(static_cast<Display*>(surface->GetXDisplay()));
                createInfo.window = surface->GetXWindow();

                VkSurfaceKHR vkSurface = VK_NULL_HANDLE;
                DAWN_TRY(CheckVkSuccess(
                    fn.CreateXcbSurfaceKHR(instance, &createInfo, nullptr, &*vkSurface),
                    "CreateXcbSurfaceKHR"));
                return vkSurface;
            }
            break;
        }
#endif  // defined(DAWN_USE_X11)

        default:
            break;
    }

    return DAWN_FORMAT_VALIDATION_ERROR("Unsupported surface type (%s) for Vulkan.",
                                        surface->GetType());
}

VkPresentModeKHR ToVulkanPresentMode(wgpu::PresentMode mode) {
    switch (mode) {
        case wgpu::PresentMode::Fifo:
            return VK_PRESENT_MODE_FIFO_KHR;
        case wgpu::PresentMode::Immediate:
            return VK_PRESENT_MODE_IMMEDIATE_KHR;
        case wgpu::PresentMode::Mailbox:
            return VK_PRESENT_MODE_MAILBOX_KHR;
    }
    UNREACHABLE();
}

uint32_t MinImageCountForPresentMode(VkPresentModeKHR mode) {
    switch (mode) {
        case VK_PRESENT_MODE_FIFO_KHR:
        case VK_PRESENT_MODE_IMMEDIATE_KHR:
            return 2;
        case VK_PRESENT_MODE_MAILBOX_KHR:
            return 3;
        default:
            break;
    }
    UNREACHABLE();
}

}  // anonymous namespace

// static
ResultOrError<Ref<SwapChain>> SwapChain::Create(Device* device,
                                                Surface* surface,
                                                NewSwapChainBase* previousSwapChain,
                                                const SwapChainDescriptor* descriptor) {
    Ref<SwapChain> swapchain = AcquireRef(new SwapChain(device, surface, descriptor));
    DAWN_TRY(swapchain->Initialize(previousSwapChain));
    return swapchain;
}

SwapChain::~SwapChain() = default;

void SwapChain::DestroyImpl() {
    SwapChainBase::DestroyImpl();
    DetachFromSurface();
}

// Note that when we need to re-create the swapchain because it is out of date,
// previousSwapChain can be set to `this`.
MaybeError SwapChain::Initialize(NewSwapChainBase* previousSwapChain) {
    Device* device = ToBackend(GetDevice());
    Adapter* adapter = ToBackend(GetDevice()->GetAdapter());

    VkSwapchainKHR previousVkSwapChain = VK_NULL_HANDLE;

    if (previousSwapChain != nullptr) {
        // TODO(crbug.com/dawn/269): The first time a surface is used with a Device, check
        // it is supported with vkGetPhysicalDeviceSurfaceSupportKHR.

        // TODO(crbug.com/dawn/269): figure out what should happen when surfaces are used by
        // multiple backends one after the other. It probably needs to block until the backend
        // and GPU are completely finished with the previous swapchain.
        DAWN_INVALID_IF(previousSwapChain->GetBackendType() != wgpu::BackendType::Vulkan,
                        "Vulkan SwapChain cannot switch backend types from %s to %s.",
                        previousSwapChain->GetBackendType(), wgpu::BackendType::Vulkan);

        // TODO(crbug.com/dawn/269): use ToBackend once OldSwapChainBase is removed.
        SwapChain* previousVulkanSwapChain = static_cast<SwapChain*>(previousSwapChain);

        // TODO(crbug.com/dawn/269): Figure out switching a single surface between multiple
        // Vulkan devices on different VkInstances. Probably needs to block too!
        VkInstance previousInstance = ToBackend(previousSwapChain->GetDevice())->GetVkInstance();
        DAWN_INVALID_IF(previousInstance != ToBackend(GetDevice())->GetVkInstance(),
                        "Vulkan SwapChain cannot switch between Vulkan instances.");

        // The previous swapchain is a dawn::native::vulkan::SwapChain so we can reuse its
        // VkSurfaceKHR provided since they are on the same instance.
        std::swap(previousVulkanSwapChain->mVkSurface, mVkSurface);

        // The previous swapchain was on the same Vulkan instance so we can use Vulkan's
        // "oldSwapchain" mechanism to ensure a seamless transition. We track the previous
        // swapchain for release immediately so it is not leaked in case of an error. (Vulkan
        // allows destroying it immediately after the call to vkCreateSwapChainKHR but tracking
        // using the fenced deleter makes the code simpler).
        std::swap(previousVulkanSwapChain->mSwapChain, previousVkSwapChain);
        ToBackend(previousSwapChain->GetDevice())
            ->GetFencedDeleter()
            ->DeleteWhenUnused(previousVkSwapChain);
    }

    if (mVkSurface == VK_NULL_HANDLE) {
        DAWN_TRY_ASSIGN(mVkSurface, CreateVulkanSurface(adapter, GetSurface()));
    }

    VulkanSurfaceInfo surfaceInfo;
    DAWN_TRY_ASSIGN(surfaceInfo, GatherSurfaceInfo(*adapter, mVkSurface));

    DAWN_TRY_ASSIGN(mConfig, ChooseConfig(surfaceInfo));

    // TODO(dawn:269): Choose config instead of hardcoding
    VkSwapchainCreateInfoKHR createInfo;
    createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR;
    createInfo.pNext = nullptr;
    createInfo.flags = 0;
    createInfo.surface = mVkSurface;
    createInfo.minImageCount = mConfig.targetImageCount;
    createInfo.imageFormat = mConfig.format;
    createInfo.imageColorSpace = mConfig.colorSpace;
    createInfo.imageExtent = mConfig.extent;
    createInfo.imageArrayLayers = 1;
    createInfo.imageUsage = mConfig.usage;
    createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE;
    createInfo.queueFamilyIndexCount = 0;
    createInfo.pQueueFamilyIndices = nullptr;
    createInfo.preTransform = mConfig.transform;
    createInfo.compositeAlpha = mConfig.alphaMode;
    createInfo.presentMode = mConfig.presentMode;
    createInfo.clipped = false;
    createInfo.oldSwapchain = previousVkSwapChain;

    DAWN_TRY(CheckVkSuccess(
        device->fn.CreateSwapchainKHR(device->GetVkDevice(), &createInfo, nullptr, &*mSwapChain),
        "CreateSwapChain"));

    // Gather the swapchain's images. Implementations are allowed to return more images than the
    // number we asked for.
    uint32_t count = 0;
    DAWN_TRY(CheckVkSuccess(
        device->fn.GetSwapchainImagesKHR(device->GetVkDevice(), mSwapChain, &count, nullptr),
        "GetSwapChainImages1"));

    mSwapChainImages.resize(count);
    DAWN_TRY(
        CheckVkSuccess(device->fn.GetSwapchainImagesKHR(device->GetVkDevice(), mSwapChain, &count,
                                                        AsVkArray(mSwapChainImages.data())),
                       "GetSwapChainImages2"));

    return {};
}

ResultOrError<SwapChain::Config> SwapChain::ChooseConfig(
    const VulkanSurfaceInfo& surfaceInfo) const {
    Config config;

    // Choose the present mode. The only guaranteed one is FIFO so it has to be the fallback for
    // all other present modes. IMMEDIATE has tearing which is generally undesirable so it can't
    // be the fallback for MAILBOX. So the fallback order is always IMMEDIATE -> MAILBOX ->
    // FIFO.
    {
        auto HasPresentMode = [](const std::vector<VkPresentModeKHR>& modes,
                                 VkPresentModeKHR target) -> bool {
            return std::find(modes.begin(), modes.end(), target) != modes.end();
        };

        VkPresentModeKHR targetMode = ToVulkanPresentMode(GetPresentMode());
        const std::array<VkPresentModeKHR, 3> kPresentModeFallbacks = {
            VK_PRESENT_MODE_IMMEDIATE_KHR,
            VK_PRESENT_MODE_MAILBOX_KHR,
            VK_PRESENT_MODE_FIFO_KHR,
        };

        // Go to the target mode.
        size_t modeIndex = 0;
        while (kPresentModeFallbacks[modeIndex] != targetMode) {
            modeIndex++;
        }

        // Find the first available fallback.
        while (!HasPresentMode(surfaceInfo.presentModes, kPresentModeFallbacks[modeIndex])) {
            modeIndex++;
        }

        ASSERT(modeIndex < kPresentModeFallbacks.size());
        config.presentMode = kPresentModeFallbacks[modeIndex];
    }

    // Choose the target width or do a blit.
    if (GetWidth() < surfaceInfo.capabilities.minImageExtent.width ||
        GetWidth() > surfaceInfo.capabilities.maxImageExtent.width ||
        GetHeight() < surfaceInfo.capabilities.minImageExtent.height ||
        GetHeight() > surfaceInfo.capabilities.maxImageExtent.height) {
        config.needsBlit = true;
    } else {
        config.extent.width = GetWidth();
        config.extent.height = GetHeight();
    }

    // Choose the target usage or do a blit.
    VkImageUsageFlags targetUsages =
        VulkanImageUsage(GetUsage(), GetDevice()->GetValidInternalFormat(GetFormat()));
    VkImageUsageFlags supportedUsages = surfaceInfo.capabilities.supportedUsageFlags;
    if (!IsSubset(targetUsages, supportedUsages)) {
        config.needsBlit = true;
    } else {
        config.usage = targetUsages;
        config.wgpuUsage = GetUsage();
    }

    // Only support BGRA8Unorm (and RGBA8Unorm on android) with SRGB color space for now.
    config.wgpuFormat = GetFormat();
    config.format = VulkanImageFormat(ToBackend(GetDevice()), config.wgpuFormat);
    config.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;

    bool formatIsSupported = false;
    for (const VkSurfaceFormatKHR& format : surfaceInfo.formats) {
        if (format.format == config.format && format.colorSpace == config.colorSpace) {
            formatIsSupported = true;
            break;
        }
    }
    if (!formatIsSupported) {
        return DAWN_INTERNAL_ERROR(absl::StrFormat(
            "Vulkan SwapChain must support %s with sRGB colorspace.", config.wgpuFormat));
    }

    // Only the identity transform with opaque alpha is supported for now.
    DAWN_INVALID_IF(
        (surfaceInfo.capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) == 0,
        "Vulkan SwapChain must support the identity transform.");

    config.transform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR;

    config.alphaMode = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;
#if !DAWN_PLATFORM_IS(ANDROID)
    DAWN_INVALID_IF(
        (surfaceInfo.capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR) == 0,
        "Vulkan SwapChain must support opaque alpha.");
#else
    // TODO(dawn:286): investigate composite alpha for WebGPU native
    VkCompositeAlphaFlagBitsKHR compositeAlphaFlags[4] = {
        VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR,
        VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR,
        VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR,
        VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR,
    };
    for (uint32_t i = 0; i < 4; i++) {
        if (surfaceInfo.capabilities.supportedCompositeAlpha & compositeAlphaFlags[i]) {
            config.alphaMode = compositeAlphaFlags[i];
            break;
        }
    }
#endif  // #if !DAWN_PLATFORM_IS(ANDROID)

    // Choose the number of images for the swapchain= and clamp it to the min and max from the
    // surface capabilities. maxImageCount = 0 means there is no limit.
    ASSERT(surfaceInfo.capabilities.maxImageCount == 0 ||
           surfaceInfo.capabilities.minImageCount <= surfaceInfo.capabilities.maxImageCount);
    uint32_t targetCount = MinImageCountForPresentMode(config.presentMode);

    targetCount = std::max(targetCount, surfaceInfo.capabilities.minImageCount);
    if (surfaceInfo.capabilities.maxImageCount != 0) {
        targetCount = std::min(targetCount, surfaceInfo.capabilities.maxImageCount);
    }

    config.targetImageCount = targetCount;

    // Choose a valid config for the swapchain texture that will receive the blit.
    if (config.needsBlit) {
        // Vulkan has provisions to have surfaces that adapt to the swapchain size. If that's
        // the case it is very likely that the target extent works, but clamp it just in case.
        // Using the target extent for the blit is better when possible so that texels don't
        // get stretched. This case is exposed by having the special "-1" value in both
        // dimensions of the extent.
        constexpr uint32_t kSpecialValue = 0xFFFF'FFFF;
        if (surfaceInfo.capabilities.currentExtent.width == kSpecialValue &&
            surfaceInfo.capabilities.currentExtent.height == kSpecialValue) {
            // extent = clamp(targetExtent, minExtent, maxExtent)
            config.extent.width = GetWidth();
            config.extent.width =
                std::min(config.extent.width, surfaceInfo.capabilities.maxImageExtent.width);
            config.extent.width =
                std::max(config.extent.width, surfaceInfo.capabilities.minImageExtent.width);

            config.extent.height = GetHeight();
            config.extent.height =
                std::min(config.extent.height, surfaceInfo.capabilities.maxImageExtent.height);
            config.extent.height =
                std::max(config.extent.height, surfaceInfo.capabilities.minImageExtent.height);
        } else {
            // If it is not an adaptable swapchain, just use the current extent for the blit
            // texture.
            config.extent = surfaceInfo.capabilities.currentExtent;
        }

        // TODO(crbug.com/dawn/269): If the swapchain image doesn't support TRANSFER_DST
        // then we'll need to have a second fallback that uses a blit shader :(
        if ((supportedUsages & VK_IMAGE_USAGE_TRANSFER_DST_BIT) == 0) {
            return DAWN_INTERNAL_ERROR(
                "SwapChain cannot fallback to a blit because of a missing "
                "VK_IMAGE_USAGE_TRANSFER_DST_BIT");
        }
        config.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT;
        config.wgpuUsage = wgpu::TextureUsage::CopyDst;
    }

    return config;
}

MaybeError SwapChain::PresentImpl() {
    Device* device = ToBackend(GetDevice());

    CommandRecordingContext* recordingContext = device->GetPendingRecordingContext();

    if (mConfig.needsBlit) {
        // TODO(dawn:269): ditto same as present below: eagerly transition the blit texture to
        // CopySrc.
        mBlitTexture->TransitionUsageNow(recordingContext, wgpu::TextureUsage::CopySrc,
                                         mBlitTexture->GetAllSubresources());
        mTexture->TransitionUsageNow(recordingContext, wgpu::TextureUsage::CopyDst,
                                     mTexture->GetAllSubresources());

        VkImageBlit region;
        region.srcSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
        region.srcSubresource.mipLevel = 0;
        region.srcSubresource.baseArrayLayer = 0;
        region.srcSubresource.layerCount = 1;
        region.srcOffsets[0] = {0, 0, 0};
        region.srcOffsets[1] = {static_cast<int32_t>(mBlitTexture->GetWidth()),
                                static_cast<int32_t>(mBlitTexture->GetHeight()), 1};

        region.dstSubresource = region.srcSubresource;
        region.dstOffsets[0] = {0, 0, 0};
        region.dstOffsets[1] = {static_cast<int32_t>(mTexture->GetWidth()),
                                static_cast<int32_t>(mTexture->GetHeight()), 1};

        device->fn.CmdBlitImage(recordingContext->commandBuffer, mBlitTexture->GetHandle(),
                                mBlitTexture->GetCurrentLayoutForSwapChain(), mTexture->GetHandle(),
                                mTexture->GetCurrentLayoutForSwapChain(), 1, &region,
                                VK_FILTER_LINEAR);

        // TODO(crbug.com/dawn/269): Find a way to reuse the blit texture between frames
        // instead of creating a new one every time. This will involve "un-destroying" the
        // texture or making the blit texture "external".
        mBlitTexture->APIDestroy();
        mBlitTexture = nullptr;
    }

    // TODO(crbug.com/dawn/269): Remove the need for this by eagerly transitioning the
    // presentable texture to present at the end of submits that use them and ideally even
    // folding that in the free layout transition at the end of render passes.
    mTexture->TransitionUsageNow(recordingContext, kPresentTextureUsage,
                                 mTexture->GetAllSubresources());

    DAWN_TRY(device->SubmitPendingCommands());

    // Assuming that the present queue is the same as the graphics queue, the proper
    // synchronization has already been done on the queue so we don't need to wait on any
    // semaphores.
    // TODO(crbug.com/dawn/269): Support the present queue not being the main queue.
    VkPresentInfoKHR presentInfo;
    presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR;
    presentInfo.pNext = nullptr;
    presentInfo.waitSemaphoreCount = 0;
    presentInfo.pWaitSemaphores = nullptr;
    presentInfo.swapchainCount = 1;
    presentInfo.pSwapchains = &*mSwapChain;
    presentInfo.pImageIndices = &mLastImageIndex;
    presentInfo.pResults = nullptr;

    // Free the texture before present so error handling doesn't skip that step.
    mTexture->APIDestroy();
    mTexture = nullptr;

    VkResult result =
        VkResult::WrapUnsafe(device->fn.QueuePresentKHR(device->GetQueue(), &presentInfo));

    switch (result) {
        case VK_SUCCESS:
        // VK_SUBOPTIMAL_KHR means "a swapchain no longer matches the surface properties
        // exactly, but can still be used to present to the surface successfully", so we
        // can also treat it as a "success" error code of vkQueuePresentKHR().
        case VK_SUBOPTIMAL_KHR:
            return {};

        // This present cannot be recovered. Re-initialize the VkSwapchain so that future
        // presents work..
        case VK_ERROR_OUT_OF_DATE_KHR:
            return Initialize(this);

        // TODO(crbug.com/dawn/269): Allow losing the surface at Dawn's API level?
        case VK_ERROR_SURFACE_LOST_KHR:
        default:
            return CheckVkSuccess(::VkResult(result), "QueuePresent");
    }
}

ResultOrError<Ref<TextureViewBase>> SwapChain::GetCurrentTextureViewImpl() {
    return GetCurrentTextureViewInternal();
}

ResultOrError<Ref<TextureViewBase>> SwapChain::GetCurrentTextureViewInternal(bool isReentrant) {
    Device* device = ToBackend(GetDevice());

    // Transiently create a semaphore that will be signaled when the presentation engine is done
    // with the swapchain image. Further operations on the image will wait for this semaphore.
    VkSemaphoreCreateInfo createInfo;
    createInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
    createInfo.pNext = nullptr;
    createInfo.flags = 0;

    VkSemaphore semaphore = VK_NULL_HANDLE;
    DAWN_TRY(CheckVkSuccess(
        device->fn.CreateSemaphore(device->GetVkDevice(), &createInfo, nullptr, &*semaphore),
        "CreateSemaphore"));

    VkResult result = VkResult::WrapUnsafe(device->fn.AcquireNextImageKHR(
        device->GetVkDevice(), mSwapChain, std::numeric_limits<uint64_t>::max(), semaphore,
        VkFence{}, &mLastImageIndex));

    if (result == VK_SUCCESS) {
        // TODO(crbug.com/dawn/269) put the semaphore on the texture so it is waited on when
        // used instead of directly on the recording context?
        device->GetPendingRecordingContext()->waitSemaphores.push_back(semaphore);
    } else {
        // The semaphore wasn't actually used (? this is unclear in the spec). Delete it when
        // we get a chance.
        ToBackend(GetDevice())->GetFencedDeleter()->DeleteWhenUnused(semaphore);
    }

    switch (result) {
        // TODO(crbug.com/dawn/269): Introduce a mechanism to notify the application that
        // the swapchain is in a suboptimal state?
        case VK_SUBOPTIMAL_KHR:
        case VK_SUCCESS:
            break;

        case VK_ERROR_OUT_OF_DATE_KHR: {
            // Prevent infinite recursive calls to GetCurrentTextureViewInternal when the
            // swapchains always return that they are out of date.
            if (isReentrant) {
                // TODO(crbug.com/dawn/269): Allow losing the surface instead?
                return DAWN_INTERNAL_ERROR(
                    "Wasn't able to recuperate the surface after a VK_ERROR_OUT_OF_DATE_KHR");
            }

            // Re-initialize the VkSwapchain and try getting the texture again.
            DAWN_TRY(Initialize(this));
            return GetCurrentTextureViewInternal(true);
        }

        // TODO(crbug.com/dawn/269): Allow losing the surface at Dawn's API level?
        case VK_ERROR_SURFACE_LOST_KHR:
        default:
            DAWN_TRY(CheckVkSuccess(::VkResult(result), "AcquireNextImage"));
    }

    TextureDescriptor textureDesc;
    textureDesc.size.width = mConfig.extent.width;
    textureDesc.size.height = mConfig.extent.height;
    textureDesc.format = mConfig.wgpuFormat;
    textureDesc.usage = mConfig.wgpuUsage;

    VkImage currentImage = mSwapChainImages[mLastImageIndex];
    mTexture = Texture::CreateForSwapChain(device, &textureDesc, currentImage);

    // In the happy path we can use the swapchain image directly.
    if (!mConfig.needsBlit) {
        return mTexture->CreateView();
    }

    // The blit texture always perfectly matches what the user requested for the swapchain.
    // We need to add the Vulkan TRANSFER_SRC flag for the vkCmdBlitImage call.
    TextureDescriptor desc = GetSwapChainBaseTextureDescriptor(this);
    DAWN_TRY_ASSIGN(mBlitTexture, Texture::Create(device, &desc, VK_IMAGE_USAGE_TRANSFER_SRC_BIT));
    return mBlitTexture->CreateView();
}

void SwapChain::DetachFromSurfaceImpl() {
    if (mTexture != nullptr) {
        mTexture->APIDestroy();
        mTexture = nullptr;
    }

    if (mBlitTexture != nullptr) {
        mBlitTexture->APIDestroy();
        mBlitTexture = nullptr;
    }

    // The swapchain images are destroyed with the swapchain.
    if (mSwapChain != VK_NULL_HANDLE) {
        ToBackend(GetDevice())->GetFencedDeleter()->DeleteWhenUnused(mSwapChain);
        mSwapChain = VK_NULL_HANDLE;
    }

    if (mVkSurface != VK_NULL_HANDLE) {
        ToBackend(GetDevice())->GetFencedDeleter()->DeleteWhenUnused(mVkSurface);
        mVkSurface = VK_NULL_HANDLE;
    }
}

}  // namespace dawn::native::vulkan
