// 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 "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"

#include <algorithm>

#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 defined(DAWN_PLATFORM_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  // defined(DAWN_PLATFORM_WINDOWS)

#if defined(DAWN_USE_X11)
                case Surface::Type::Xlib: {
                    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 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 with SRGB color space for now.
        bool hasBGRA8Unorm = false;
        for (const VkSurfaceFormatKHR& format : surfaceInfo.formats) {
            if (format.format == VK_FORMAT_B8G8R8A8_UNORM &&
                format.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) {
                hasBGRA8Unorm = true;
                break;
            }
        }
        if (!hasBGRA8Unorm) {
            return DAWN_INTERNAL_ERROR(
                "Vulkan SwapChain must support BGRA8Unorm with sRGB colorspace.");
        }
        config.format = VK_FORMAT_B8G8R8A8_UNORM;
        config.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR;
        config.wgpuFormat = wgpu::TextureFormat::BGRA8Unorm;

        // 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;

        DAWN_INVALID_IF((surfaceInfo.capabilities.supportedCompositeAlpha &
                         VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR) == 0,
                        "Vulkan SwapChain must support opaque alpha.");

        config.alphaMode = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR;

        // 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 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<TextureViewBase*> SwapChain::GetCurrentTextureViewImpl() {
        return GetCurrentTextureViewInternal();
    }

    ResultOrError<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) {
            // TODO(dawn:723): change to not use AcquireRef for reentrant object creation.
            return mTexture->APICreateView();
        }

        // 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));
        // TODO(dawn:723): change to not use AcquireRef for reentrant object creation.
        return mBlitTexture->APICreateView();
    }

    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
