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

#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
