// Copyright 2019 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 "common/Math.h"
#include "tests/DawnTest.h"

#include "common/vulkan_platform.h"
#include "dawn_native/VulkanBackend.h"
#include "dawn_native/vulkan/AdapterVk.h"
#include "dawn_native/vulkan/DeviceVk.h"
#include "dawn_native/vulkan/FencedDeleter.h"
#include "dawn_native/vulkan/ResourceMemoryAllocatorVk.h"
#include "dawn_native/vulkan/TextureVk.h"
#include "utils/SystemUtils.h"
#include "utils/WGPUHelpers.h"

namespace dawn_native { namespace vulkan {

    namespace {

        class VulkanImageWrappingTestBase : public DawnTest {
          public:
            void SetUp() override {
                DawnTest::SetUp();
                if (UsesWire()) {
                    return;
                }

                deviceVk = reinterpret_cast<dawn_native::vulkan::Device*>(device.Get());
            }

            // Creates a VkImage with external memory
            ::VkResult CreateImage(dawn_native::vulkan::Device* deviceVk,
                                   uint32_t width,
                                   uint32_t height,
                                   VkFormat format,
                                   VkImage* image) {
                VkExternalMemoryImageCreateInfoKHR externalInfo;
                externalInfo.sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR;
                externalInfo.pNext = nullptr;
                externalInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;

                auto usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
                             VK_IMAGE_USAGE_TRANSFER_DST_BIT;

                VkImageCreateInfo createInfo;
                createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
                createInfo.pNext = &externalInfo;
                createInfo.flags = VK_IMAGE_CREATE_ALIAS_BIT_KHR;
                createInfo.imageType = VK_IMAGE_TYPE_2D;
                createInfo.format = format;
                createInfo.extent = {width, height, 1};
                createInfo.mipLevels = 1;
                createInfo.arrayLayers = 1;
                createInfo.samples = VK_SAMPLE_COUNT_1_BIT;
                createInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
                createInfo.usage = usage;
                createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
                createInfo.queueFamilyIndexCount = 0;
                createInfo.pQueueFamilyIndices = nullptr;
                createInfo.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;

                return deviceVk->fn.CreateImage(deviceVk->GetVkDevice(), &createInfo, nullptr,
                                                &**image);
            }

            // Allocates memory for an image
            ::VkResult AllocateMemory(dawn_native::vulkan::Device* deviceVk,
                                      VkImage handle,
                                      VkDeviceMemory* allocation,
                                      VkDeviceSize* allocationSize,
                                      uint32_t* memoryTypeIndex) {
                // Create the image memory and associate it with the container
                VkMemoryRequirements requirements;
                deviceVk->fn.GetImageMemoryRequirements(deviceVk->GetVkDevice(), handle,
                                                        &requirements);

                // Import memory from file descriptor
                VkExportMemoryAllocateInfoKHR externalInfo;
                externalInfo.sType = VK_STRUCTURE_TYPE_EXPORT_MEMORY_ALLOCATE_INFO_KHR;
                externalInfo.pNext = nullptr;
                externalInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;

                int bestType = deviceVk->GetResourceMemoryAllocatorForTesting()->FindBestTypeIndex(
                    requirements, false);
                VkMemoryAllocateInfo allocateInfo;
                allocateInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
                allocateInfo.pNext = &externalInfo;
                allocateInfo.allocationSize = requirements.size;
                allocateInfo.memoryTypeIndex = static_cast<uint32_t>(bestType);

                *allocationSize = allocateInfo.allocationSize;
                *memoryTypeIndex = allocateInfo.memoryTypeIndex;

                return deviceVk->fn.AllocateMemory(deviceVk->GetVkDevice(), &allocateInfo, nullptr,
                                                   &**allocation);
            }

            // Binds memory to an image
            ::VkResult BindMemory(dawn_native::vulkan::Device* deviceVk,
                                  VkImage handle,
                                  VkDeviceMemory* memory) {
                return deviceVk->fn.BindImageMemory(deviceVk->GetVkDevice(), handle, *memory, 0);
            }

            // Extracts a file descriptor representing memory on a device
            int GetMemoryFd(dawn_native::vulkan::Device* deviceVk, VkDeviceMemory memory) {
                VkMemoryGetFdInfoKHR getFdInfo;
                getFdInfo.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR;
                getFdInfo.pNext = nullptr;
                getFdInfo.memory = memory;
                getFdInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR;

                int memoryFd = -1;
                deviceVk->fn.GetMemoryFdKHR(deviceVk->GetVkDevice(), &getFdInfo, &memoryFd);

                EXPECT_GE(memoryFd, 0) << "Failed to get file descriptor for external memory";
                return memoryFd;
            }

            // Prepares and exports memory for an image on a given device
            void CreateBindExportImage(dawn_native::vulkan::Device* deviceVk,
                                       uint32_t width,
                                       uint32_t height,
                                       VkFormat format,
                                       VkImage* handle,
                                       VkDeviceMemory* allocation,
                                       VkDeviceSize* allocationSize,
                                       uint32_t* memoryTypeIndex,
                                       int* memoryFd) {
                ::VkResult result = CreateImage(deviceVk, width, height, format, handle);
                EXPECT_EQ(result, VK_SUCCESS) << "Failed to create external image";

                ::VkResult resultBool =
                    AllocateMemory(deviceVk, *handle, allocation, allocationSize, memoryTypeIndex);
                EXPECT_EQ(resultBool, VK_SUCCESS) << "Failed to allocate external memory";

                result = BindMemory(deviceVk, *handle, allocation);
                EXPECT_EQ(result, VK_SUCCESS) << "Failed to bind image memory";

                *memoryFd = GetMemoryFd(deviceVk, *allocation);
            }

            // Wraps a vulkan image from external memory
            wgpu::Texture WrapVulkanImage(wgpu::Device dawnDevice,
                                          const wgpu::TextureDescriptor* textureDescriptor,
                                          int memoryFd,
                                          VkDeviceSize allocationSize,
                                          uint32_t memoryTypeIndex,
                                          std::vector<int> waitFDs,
                                          bool isCleared = true,
                                          bool expectValid = true) {
                dawn_native::vulkan::ExternalImageDescriptorOpaqueFD descriptor;
                descriptor.cTextureDescriptor =
                    reinterpret_cast<const WGPUTextureDescriptor*>(textureDescriptor);
                descriptor.isCleared = isCleared;
                descriptor.allocationSize = allocationSize;
                descriptor.memoryTypeIndex = memoryTypeIndex;
                descriptor.memoryFD = memoryFd;
                descriptor.waitFDs = waitFDs;

                WGPUTexture texture =
                    dawn_native::vulkan::WrapVulkanImage(dawnDevice.Get(), &descriptor);

                if (expectValid) {
                    EXPECT_NE(texture, nullptr) << "Failed to wrap image, are external memory / "
                                                   "semaphore extensions supported?";
                } else {
                    EXPECT_EQ(texture, nullptr);
                }

                return wgpu::Texture::Acquire(texture);
            }

            // Exports the signal from a wrapped texture and ignores it
            // We have to export the signal before destroying the wrapped texture else it's an
            // assertion failure
            void IgnoreSignalSemaphore(wgpu::Device dawnDevice, wgpu::Texture wrappedTexture) {
                int fd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(dawnDevice.Get(),
                                                                            wrappedTexture.Get());
                ASSERT_NE(fd, -1);
                close(fd);
            }

          protected:
            dawn_native::vulkan::Device* deviceVk;
        };

    }  // anonymous namespace

    class VulkanImageWrappingValidationTests : public VulkanImageWrappingTestBase {
      public:
        void SetUp() override {
            VulkanImageWrappingTestBase::SetUp();
            if (UsesWire()) {
                return;
            }

            CreateBindExportImage(deviceVk, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, &defaultImage,
                                  &defaultAllocation, &defaultAllocationSize,
                                  &defaultMemoryTypeIndex, &defaultFd);
            defaultDescriptor.dimension = wgpu::TextureDimension::e2D;
            defaultDescriptor.format = wgpu::TextureFormat::RGBA8Unorm;
            defaultDescriptor.size = {1, 1, 1};
            defaultDescriptor.sampleCount = 1;
            defaultDescriptor.arrayLayerCount = 1;
            defaultDescriptor.mipLevelCount = 1;
            defaultDescriptor.usage = wgpu::TextureUsage::OutputAttachment |
                                      wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
        }

        void TearDown() override {
            if (UsesWire()) {
                VulkanImageWrappingTestBase::TearDown();
                return;
            }

            deviceVk->GetFencedDeleter()->DeleteWhenUnused(defaultImage);
            deviceVk->GetFencedDeleter()->DeleteWhenUnused(defaultAllocation);
            VulkanImageWrappingTestBase::TearDown();
        }

      protected:
        wgpu::TextureDescriptor defaultDescriptor;
        VkImage defaultImage;
        VkDeviceMemory defaultAllocation;
        VkDeviceSize defaultAllocationSize;
        uint32_t defaultMemoryTypeIndex;
        int defaultFd;
    };

    // Test no error occurs if the import is valid
    TEST_P(VulkanImageWrappingValidationTests, SuccessfulImport) {
        DAWN_SKIP_TEST_IF(UsesWire());
        wgpu::Texture texture =
            WrapVulkanImage(device, &defaultDescriptor, defaultFd, defaultAllocationSize,
                            defaultMemoryTypeIndex, {}, true, true);
        EXPECT_NE(texture.Get(), nullptr);
        IgnoreSignalSemaphore(device, texture);
    }

    // Test an error occurs if the texture descriptor is missing
    TEST_P(VulkanImageWrappingValidationTests, MissingTextureDescriptor) {
        DAWN_SKIP_TEST_IF(UsesWire());
        ASSERT_DEVICE_ERROR(wgpu::Texture texture =
                                WrapVulkanImage(device, nullptr, defaultFd, defaultAllocationSize,
                                                defaultMemoryTypeIndex, {}, true, false));
        EXPECT_EQ(texture.Get(), nullptr);
    }

    // Test an error occurs if the texture descriptor is invalid
    TEST_P(VulkanImageWrappingValidationTests, InvalidTextureDescriptor) {
        DAWN_SKIP_TEST_IF(UsesWire());
        wgpu::ChainedStruct chainedDescriptor;
        defaultDescriptor.nextInChain = &chainedDescriptor;

        ASSERT_DEVICE_ERROR(wgpu::Texture texture = WrapVulkanImage(
                                device, &defaultDescriptor, defaultFd, defaultAllocationSize,
                                defaultMemoryTypeIndex, {}, true, false));
        EXPECT_EQ(texture.Get(), nullptr);
    }

    // Test an error occurs if the descriptor dimension isn't 2D
    TEST_P(VulkanImageWrappingValidationTests, InvalidTextureDimension) {
        DAWN_SKIP_TEST_IF(UsesWire());
        defaultDescriptor.dimension = wgpu::TextureDimension::e1D;

        ASSERT_DEVICE_ERROR(wgpu::Texture texture = WrapVulkanImage(
                                device, &defaultDescriptor, defaultFd, defaultAllocationSize,
                                defaultMemoryTypeIndex, {}, true, false));
        EXPECT_EQ(texture.Get(), nullptr);
    }

    // Test an error occurs if the descriptor mip level count isn't 1
    TEST_P(VulkanImageWrappingValidationTests, InvalidMipLevelCount) {
        DAWN_SKIP_TEST_IF(UsesWire());
        defaultDescriptor.mipLevelCount = 2;

        ASSERT_DEVICE_ERROR(wgpu::Texture texture = WrapVulkanImage(
                                device, &defaultDescriptor, defaultFd, defaultAllocationSize,
                                defaultMemoryTypeIndex, {}, true, false));
        EXPECT_EQ(texture.Get(), nullptr);
    }

    // Test an error occurs if the descriptor array layer count isn't 1
    TEST_P(VulkanImageWrappingValidationTests, InvalidArrayLayerCount) {
        DAWN_SKIP_TEST_IF(UsesWire());
        defaultDescriptor.arrayLayerCount = 2;

        ASSERT_DEVICE_ERROR(wgpu::Texture texture = WrapVulkanImage(
                                device, &defaultDescriptor, defaultFd, defaultAllocationSize,
                                defaultMemoryTypeIndex, {}, true, false));
        EXPECT_EQ(texture.Get(), nullptr);
    }

    // Test an error occurs if the descriptor sample count isn't 1
    TEST_P(VulkanImageWrappingValidationTests, InvalidSampleCount) {
        DAWN_SKIP_TEST_IF(UsesWire());
        defaultDescriptor.sampleCount = 4;

        ASSERT_DEVICE_ERROR(wgpu::Texture texture = WrapVulkanImage(
                                device, &defaultDescriptor, defaultFd, defaultAllocationSize,
                                defaultMemoryTypeIndex, {}, true, false));
        EXPECT_EQ(texture.Get(), nullptr);
    }

    // Test an error occurs if we try to export the signal semaphore twice
    TEST_P(VulkanImageWrappingValidationTests, DoubleSignalSemaphoreExport) {
        DAWN_SKIP_TEST_IF(UsesWire());
        wgpu::Texture texture =
            WrapVulkanImage(device, &defaultDescriptor, defaultFd, defaultAllocationSize,
                            defaultMemoryTypeIndex, {}, true, true);
        ASSERT_NE(texture.Get(), nullptr);
        IgnoreSignalSemaphore(device, texture);
        ASSERT_DEVICE_ERROR(int fd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
                                device.Get(), texture.Get()));
        ASSERT_EQ(fd, -1);
    }

    // Test an error occurs if we try to export the signal semaphore from a normal texture
    TEST_P(VulkanImageWrappingValidationTests, NormalTextureSignalSemaphoreExport) {
        DAWN_SKIP_TEST_IF(UsesWire());
        wgpu::Texture texture = device.CreateTexture(&defaultDescriptor);
        ASSERT_NE(texture.Get(), nullptr);
        ASSERT_DEVICE_ERROR(int fd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
                                device.Get(), texture.Get()));
        ASSERT_EQ(fd, -1);
    }

    // Test an error occurs if we try to export the signal semaphore from a destroyed texture
    TEST_P(VulkanImageWrappingValidationTests, DestroyedTextureSignalSemaphoreExport) {
        DAWN_SKIP_TEST_IF(UsesWire());
        wgpu::Texture texture = device.CreateTexture(&defaultDescriptor);
        ASSERT_NE(texture.Get(), nullptr);
        texture.Destroy();
        ASSERT_DEVICE_ERROR(int fd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
                                device.Get(), texture.Get()));
        ASSERT_EQ(fd, -1);
    }

    // Fixture to test using external memory textures through different usages.
    // These tests are skipped if the harness is using the wire.
    class VulkanImageWrappingUsageTests : public VulkanImageWrappingTestBase {
      public:
        void SetUp() override {
            VulkanImageWrappingTestBase::SetUp();
            if (UsesWire()) {
                return;
            }

            // Create another device based on the original
            backendAdapter =
                reinterpret_cast<dawn_native::vulkan::Adapter*>(deviceVk->GetAdapter());
            deviceDescriptor.forceEnabledToggles = GetParam().forceEnabledWorkarounds;
            deviceDescriptor.forceDisabledToggles = GetParam().forceDisabledWorkarounds;

            secondDeviceVk = reinterpret_cast<dawn_native::vulkan::Device*>(
                backendAdapter->CreateDevice(&deviceDescriptor));
            secondDevice = wgpu::Device::Acquire(reinterpret_cast<WGPUDevice>(secondDeviceVk));

            CreateBindExportImage(deviceVk, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, &defaultImage,
                                  &defaultAllocation, &defaultAllocationSize,
                                  &defaultMemoryTypeIndex, &defaultFd);
            defaultDescriptor.dimension = wgpu::TextureDimension::e2D;
            defaultDescriptor.format = wgpu::TextureFormat::RGBA8Unorm;
            defaultDescriptor.size = {1, 1, 1};
            defaultDescriptor.sampleCount = 1;
            defaultDescriptor.arrayLayerCount = 1;
            defaultDescriptor.mipLevelCount = 1;
            defaultDescriptor.usage = wgpu::TextureUsage::OutputAttachment |
                                      wgpu::TextureUsage::CopySrc | wgpu::TextureUsage::CopyDst;
        }

        void TearDown() override {
            if (UsesWire()) {
                VulkanImageWrappingTestBase::TearDown();
                return;
            }

            deviceVk->GetFencedDeleter()->DeleteWhenUnused(defaultImage);
            deviceVk->GetFencedDeleter()->DeleteWhenUnused(defaultAllocation);
            VulkanImageWrappingTestBase::TearDown();
        }

      protected:
        wgpu::Device secondDevice;
        dawn_native::vulkan::Device* secondDeviceVk;

        dawn_native::vulkan::Adapter* backendAdapter;
        dawn_native::DeviceDescriptor deviceDescriptor;

        wgpu::TextureDescriptor defaultDescriptor;
        VkImage defaultImage;
        VkDeviceMemory defaultAllocation;
        VkDeviceSize defaultAllocationSize;
        uint32_t defaultMemoryTypeIndex;
        int defaultFd;

        // Clear a texture on a given device
        void ClearImage(wgpu::Device dawnDevice,
                        wgpu::Texture wrappedTexture,
                        wgpu::Color clearColor) {
            wgpu::TextureView wrappedView = wrappedTexture.CreateView();

            // Submit a clear operation
            utils::ComboRenderPassDescriptor renderPassDescriptor({wrappedView}, {});
            renderPassDescriptor.cColorAttachments[0].clearColor = clearColor;

            wgpu::CommandEncoder encoder = dawnDevice.CreateCommandEncoder();
            wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPassDescriptor);
            pass.EndPass();

            wgpu::CommandBuffer commands = encoder.Finish();

            wgpu::Queue queue = dawnDevice.GetDefaultQueue();
            queue.Submit(1, &commands);
        }

        // Submits a 1x1x1 copy from source to destination
        void SimpleCopyTextureToTexture(wgpu::Device dawnDevice,
                                        wgpu::Queue dawnQueue,
                                        wgpu::Texture source,
                                        wgpu::Texture destination) {
            wgpu::TextureCopyView copySrc;
            copySrc.texture = source;
            copySrc.mipLevel = 0;
            copySrc.arrayLayer = 0;
            copySrc.origin = {0, 0, 0};

            wgpu::TextureCopyView copyDst;
            copyDst.texture = destination;
            copyDst.mipLevel = 0;
            copyDst.arrayLayer = 0;
            copyDst.origin = {0, 0, 0};

            wgpu::Extent3D copySize = {1, 1, 1};

            wgpu::CommandEncoder encoder = dawnDevice.CreateCommandEncoder();
            encoder.CopyTextureToTexture(&copySrc, &copyDst, &copySize);
            wgpu::CommandBuffer commands = encoder.Finish();

            dawnQueue.Submit(1, &commands);
        }
    };

    // Clear an image in |secondDevice|
    // Verify clear color is visible in |device|
    TEST_P(VulkanImageWrappingUsageTests, ClearImageAcrossDevices) {
        DAWN_SKIP_TEST_IF(UsesWire());

        // Import the image on |secondDevice|
        wgpu::Texture wrappedTexture =
            WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd, defaultAllocationSize,
                            defaultMemoryTypeIndex, {});

        // Clear |wrappedTexture| on |secondDevice|
        ClearImage(secondDevice, wrappedTexture, {1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f});

        int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
                                                                          wrappedTexture.Get());

        // Import the image to |device|, making sure we wait on signalFd
        int memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
        wgpu::Texture nextWrappedTexture =
            WrapVulkanImage(device, &defaultDescriptor, memoryFd, defaultAllocationSize,
                            defaultMemoryTypeIndex, {signalFd});

        // Verify |device| sees the changes from |secondDevice|
        EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), nextWrappedTexture, 0, 0);

        IgnoreSignalSemaphore(device, nextWrappedTexture);
    }

    // Import texture to |device| and |secondDevice|
    // Clear image in |secondDevice|
    // Verify clear color is visible in |device|
    // Verify the very first import into |device| also sees the change, since it should
    // alias the same memory
    TEST_P(VulkanImageWrappingUsageTests, ClearImageAcrossDevicesAliased) {
        DAWN_SKIP_TEST_IF(UsesWire());
        // Import the image on |device
        wgpu::Texture wrappedTextureAlias =
            WrapVulkanImage(device, &defaultDescriptor, defaultFd, defaultAllocationSize,
                            defaultMemoryTypeIndex, {});

        int memoryFd = GetMemoryFd(deviceVk, defaultAllocation);

        // Import the image on |secondDevice|
        wgpu::Texture wrappedTexture =
            WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd, defaultAllocationSize,
                            defaultMemoryTypeIndex, {});

        // Clear |wrappedTexture| on |secondDevice|
        ClearImage(secondDevice, wrappedTexture, {1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f});

        int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
                                                                          wrappedTexture.Get());

        // Import the image to |device|, making sure we wait on signalFd
        memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
        wgpu::Texture nextWrappedTexture =
            WrapVulkanImage(device, &defaultDescriptor, memoryFd, defaultAllocationSize,
                            defaultMemoryTypeIndex, {signalFd});

        // Verify |device| sees the changes from |secondDevice| (waits)
        EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), nextWrappedTexture, 0, 0);

        // Verify aliased texture sees changes from |secondDevice| (without waiting!)
        EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), wrappedTextureAlias, 0, 0);

        IgnoreSignalSemaphore(device, nextWrappedTexture);
        IgnoreSignalSemaphore(device, wrappedTextureAlias);
    }

    // Clear an image in |secondDevice|
    // Verify clear color is not visible in |device| if we import the texture as not cleared
    TEST_P(VulkanImageWrappingUsageTests, UnclearedTextureIsCleared) {
        DAWN_SKIP_TEST_IF(UsesWire());

        // Import the image on |secondDevice|
        wgpu::Texture wrappedTexture =
            WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd, defaultAllocationSize,
                            defaultMemoryTypeIndex, {});

        // Clear |wrappedTexture| on |secondDevice|
        ClearImage(secondDevice, wrappedTexture, {1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f});

        int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
                                                                          wrappedTexture.Get());

        // Import the image to |device|, making sure we wait on signalFd
        int memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
        wgpu::Texture nextWrappedTexture =
            WrapVulkanImage(device, &defaultDescriptor, memoryFd, defaultAllocationSize,
                            defaultMemoryTypeIndex, {signalFd}, false);

        // Verify |device| doesn't see the changes from |secondDevice|
        EXPECT_PIXEL_RGBA8_EQ(RGBA8(0, 0, 0, 0), nextWrappedTexture, 0, 0);

        IgnoreSignalSemaphore(device, nextWrappedTexture);
    }

    // Import a texture into |secondDevice|
    // Issue a copy of the imported texture inside |device| to |copyDstTexture|
    // Verify the clear color from |secondDevice| is visible in |copyDstTexture|
    TEST_P(VulkanImageWrappingUsageTests, CopyTextureToTextureSrcSync) {
        DAWN_SKIP_TEST_IF(UsesWire());

        // Import the image on |secondDevice|
        wgpu::Texture wrappedTexture =
            WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd, defaultAllocationSize,
                            defaultMemoryTypeIndex, {});

        // Clear |wrappedTexture| on |secondDevice|
        ClearImage(secondDevice, wrappedTexture, {1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f});

        int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
                                                                          wrappedTexture.Get());

        // Import the image to |device|, making sure we wait on |signalFd|
        int memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
        wgpu::Texture deviceWrappedTexture =
            WrapVulkanImage(device, &defaultDescriptor, memoryFd, defaultAllocationSize,
                            defaultMemoryTypeIndex, {signalFd});

        // Create a second texture on |device|
        wgpu::Texture copyDstTexture = device.CreateTexture(&defaultDescriptor);

        // Copy |deviceWrappedTexture| into |copyDstTexture|
        SimpleCopyTextureToTexture(device, queue, deviceWrappedTexture, copyDstTexture);

        // Verify |copyDstTexture| sees changes from |secondDevice|
        EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), copyDstTexture, 0, 0);

        IgnoreSignalSemaphore(device, deviceWrappedTexture);
    }

    // Import a texture into |device|
    // Copy color A into texture on |device|
    // Import same texture into |secondDevice|, waiting on the copy signal
    // Copy color B using Texture to Texture copy on |secondDevice|
    // Import texture back into |device|, waiting on color B signal
    // Verify texture contains color B
    // If texture destination isn't synchronized, |secondDevice| could copy color B
    // into the texture first, then |device| writes color A
    TEST_P(VulkanImageWrappingUsageTests, CopyTextureToTextureDstSync) {
        DAWN_SKIP_TEST_IF(UsesWire());

        // Import the image on |device|
        wgpu::Texture wrappedTexture =
            WrapVulkanImage(device, &defaultDescriptor, defaultFd, defaultAllocationSize,
                            defaultMemoryTypeIndex, {});

        // Clear |wrappedTexture| on |device|
        ClearImage(device, wrappedTexture, {5 / 255.0f, 6 / 255.0f, 7 / 255.0f, 8 / 255.0f});

        int signalFd =
            dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(device.Get(), wrappedTexture.Get());

        // Import the image to |secondDevice|, making sure we wait on |signalFd|
        int memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
        wgpu::Texture secondDeviceWrappedTexture =
            WrapVulkanImage(secondDevice, &defaultDescriptor, memoryFd, defaultAllocationSize,
                            defaultMemoryTypeIndex, {signalFd});

        // Create a texture with color B on |secondDevice|
        wgpu::Texture copySrcTexture = secondDevice.CreateTexture(&defaultDescriptor);
        ClearImage(secondDevice, copySrcTexture, {1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f});

        // Copy color B on |secondDevice|
        wgpu::Queue secondDeviceQueue = secondDevice.GetDefaultQueue();
        SimpleCopyTextureToTexture(secondDevice, secondDeviceQueue, copySrcTexture,
                                   secondDeviceWrappedTexture);

        // Re-import back into |device|, waiting on |secondDevice|'s signal
        signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
            secondDevice.Get(), secondDeviceWrappedTexture.Get());
        memoryFd = GetMemoryFd(deviceVk, defaultAllocation);

        wgpu::Texture nextWrappedTexture =
            WrapVulkanImage(device, &defaultDescriptor, memoryFd, defaultAllocationSize,
                            defaultMemoryTypeIndex, {signalFd});

        // Verify |nextWrappedTexture| contains the color from our copy
        EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), nextWrappedTexture, 0, 0);

        IgnoreSignalSemaphore(device, nextWrappedTexture);
    }

    // Import a texture from |secondDevice|
    // Issue a copy of the imported texture inside |device| to |copyDstBuffer|
    // Verify the clear color from |secondDevice| is visible in |copyDstBuffer|
    TEST_P(VulkanImageWrappingUsageTests, CopyTextureToBufferSrcSync) {
        DAWN_SKIP_TEST_IF(UsesWire());

        // Import the image on |secondDevice|
        wgpu::Texture wrappedTexture =
            WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd, defaultAllocationSize,
                            defaultMemoryTypeIndex, {});

        // Clear |wrappedTexture| on |secondDevice|
        ClearImage(secondDevice, wrappedTexture, {1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f});

        int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
                                                                          wrappedTexture.Get());

        // Import the image to |device|, making sure we wait on |signalFd|
        int memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
        wgpu::Texture deviceWrappedTexture =
            WrapVulkanImage(device, &defaultDescriptor, memoryFd, defaultAllocationSize,
                            defaultMemoryTypeIndex, {signalFd});

        // Create a destination buffer on |device|
        wgpu::BufferDescriptor bufferDesc;
        bufferDesc.size = 4;
        bufferDesc.usage = wgpu::BufferUsage::CopyDst | wgpu::BufferUsage::CopySrc;
        wgpu::Buffer copyDstBuffer = device.CreateBuffer(&bufferDesc);

        // Copy |deviceWrappedTexture| into |copyDstBuffer|
        wgpu::TextureCopyView copySrc;
        copySrc.texture = deviceWrappedTexture;
        copySrc.mipLevel = 0;
        copySrc.arrayLayer = 0;
        copySrc.origin = {0, 0, 0};

        wgpu::BufferCopyView copyDst;
        copyDst.buffer = copyDstBuffer;
        copyDst.offset = 0;
        copyDst.bytesPerRow = 256;
        copyDst.rowsPerImage = 0;

        wgpu::Extent3D copySize = {1, 1, 1};

        wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
        encoder.CopyTextureToBuffer(&copySrc, &copyDst, &copySize);
        wgpu::CommandBuffer commands = encoder.Finish();
        queue.Submit(1, &commands);

        // Verify |copyDstBuffer| sees changes from |secondDevice|
        uint32_t expected = 0x04030201;
        EXPECT_BUFFER_U32_EQ(expected, copyDstBuffer, 0);

        IgnoreSignalSemaphore(device, deviceWrappedTexture);
    }

    // Import a texture into |device|
    // Copy color A into texture on |device|
    // Import same texture into |secondDevice|, waiting on the copy signal
    // Copy color B using Buffer to Texture copy on |secondDevice|
    // Import texture back into |device|, waiting on color B signal
    // Verify texture contains color B
    // If texture destination isn't synchronized, |secondDevice| could copy color B
    // into the texture first, then |device| writes color A
    TEST_P(VulkanImageWrappingUsageTests, CopyBufferToTextureDstSync) {
        DAWN_SKIP_TEST_IF(UsesWire());

        // Import the image on |device|
        wgpu::Texture wrappedTexture =
            WrapVulkanImage(device, &defaultDescriptor, defaultFd, defaultAllocationSize,
                            defaultMemoryTypeIndex, {});

        // Clear |wrappedTexture| on |device|
        ClearImage(device, wrappedTexture, {5 / 255.0f, 6 / 255.0f, 7 / 255.0f, 8 / 255.0f});

        int signalFd =
            dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(device.Get(), wrappedTexture.Get());

        // Import the image to |secondDevice|, making sure we wait on |signalFd|
        int memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
        wgpu::Texture secondDeviceWrappedTexture =
            WrapVulkanImage(secondDevice, &defaultDescriptor, memoryFd, defaultAllocationSize,
                            defaultMemoryTypeIndex, {signalFd});

        // Copy color B on |secondDevice|
        wgpu::Queue secondDeviceQueue = secondDevice.GetDefaultQueue();

        // Create a buffer on |secondDevice|
        wgpu::Buffer copySrcBuffer =
            utils::CreateBufferFromData(secondDevice, wgpu::BufferUsage::CopySrc, {0x04030201});

        // Copy |copySrcBuffer| into |secondDeviceWrappedTexture|
        wgpu::BufferCopyView copySrc;
        copySrc.buffer = copySrcBuffer;
        copySrc.offset = 0;
        copySrc.bytesPerRow = 256;
        copySrc.rowsPerImage = 0;

        wgpu::TextureCopyView copyDst;
        copyDst.texture = secondDeviceWrappedTexture;
        copyDst.mipLevel = 0;
        copyDst.arrayLayer = 0;
        copyDst.origin = {0, 0, 0};

        wgpu::Extent3D copySize = {1, 1, 1};

        wgpu::CommandEncoder encoder = secondDevice.CreateCommandEncoder();
        encoder.CopyBufferToTexture(&copySrc, &copyDst, &copySize);
        wgpu::CommandBuffer commands = encoder.Finish();
        secondDeviceQueue.Submit(1, &commands);

        // Re-import back into |device|, waiting on |secondDevice|'s signal
        signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
            secondDevice.Get(), secondDeviceWrappedTexture.Get());
        memoryFd = GetMemoryFd(deviceVk, defaultAllocation);

        wgpu::Texture nextWrappedTexture =
            WrapVulkanImage(device, &defaultDescriptor, memoryFd, defaultAllocationSize,
                            defaultMemoryTypeIndex, {signalFd});

        // Verify |nextWrappedTexture| contains the color from our copy
        EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), nextWrappedTexture, 0, 0);

        IgnoreSignalSemaphore(device, nextWrappedTexture);
    }

    // Import a texture from |secondDevice|
    // Issue a copy of the imported texture inside |device| to |copyDstTexture|
    // Issue second copy to |secondCopyDstTexture|
    // Verify the clear color from |secondDevice| is visible in both copies
    TEST_P(VulkanImageWrappingUsageTests, DoubleTextureUsage) {
        DAWN_SKIP_TEST_IF(UsesWire());

        // Import the image on |secondDevice|
        wgpu::Texture wrappedTexture =
            WrapVulkanImage(secondDevice, &defaultDescriptor, defaultFd, defaultAllocationSize,
                            defaultMemoryTypeIndex, {});

        // Clear |wrappedTexture| on |secondDevice|
        ClearImage(secondDevice, wrappedTexture, {1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f});

        int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
                                                                          wrappedTexture.Get());

        // Import the image to |device|, making sure we wait on |signalFd|
        int memoryFd = GetMemoryFd(deviceVk, defaultAllocation);
        wgpu::Texture deviceWrappedTexture =
            WrapVulkanImage(device, &defaultDescriptor, memoryFd, defaultAllocationSize,
                            defaultMemoryTypeIndex, {signalFd});

        // Create a second texture on |device|
        wgpu::Texture copyDstTexture = device.CreateTexture(&defaultDescriptor);

        // Create a third texture on |device|
        wgpu::Texture secondCopyDstTexture = device.CreateTexture(&defaultDescriptor);

        // Copy |deviceWrappedTexture| into |copyDstTexture|
        SimpleCopyTextureToTexture(device, queue, deviceWrappedTexture, copyDstTexture);

        // Copy |deviceWrappedTexture| into |secondCopyDstTexture|
        SimpleCopyTextureToTexture(device, queue, deviceWrappedTexture, secondCopyDstTexture);

        // Verify |copyDstTexture| sees changes from |secondDevice|
        EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), copyDstTexture, 0, 0);

        // Verify |secondCopyDstTexture| sees changes from |secondDevice|
        EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), secondCopyDstTexture, 0, 0);

        IgnoreSignalSemaphore(device, deviceWrappedTexture);
    }

    // Tex A on device 3 (external export)
    // Tex B on device 2 (external export)
    // Tex C on device 1 (external export)
    // Clear color for A on device 3
    // Copy A->B on device 3
    // Copy B->C on device 2 (wait on B from previous op)
    // Copy C->D on device 1 (wait on C from previous op)
    // Verify D has same color as A
    TEST_P(VulkanImageWrappingUsageTests, ChainTextureCopy) {
        DAWN_SKIP_TEST_IF(UsesWire());

        // Close |defaultFd| since this test doesn't import it anywhere
        close(defaultFd);

        // device 1 = |device|
        // device 2 = |secondDevice|
        // Create device 3
        dawn_native::vulkan::Device* thirdDeviceVk = reinterpret_cast<dawn_native::vulkan::Device*>(
            backendAdapter->CreateDevice(&deviceDescriptor));
        wgpu::Device thirdDevice =
            wgpu::Device::Acquire(reinterpret_cast<WGPUDevice>(thirdDeviceVk));

        // Make queue for device 2 and 3
        wgpu::Queue secondDeviceQueue = secondDevice.GetDefaultQueue();
        wgpu::Queue thirdDeviceQueue = thirdDevice.GetDefaultQueue();

        // Allocate memory for A, B, C
        VkImage imageA;
        VkDeviceMemory allocationA;
        int memoryFdA;
        VkDeviceSize allocationSizeA;
        uint32_t memoryTypeIndexA;
        CreateBindExportImage(thirdDeviceVk, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, &imageA, &allocationA,
                              &allocationSizeA, &memoryTypeIndexA, &memoryFdA);

        VkImage imageB;
        VkDeviceMemory allocationB;
        int memoryFdB;
        VkDeviceSize allocationSizeB;
        uint32_t memoryTypeIndexB;
        CreateBindExportImage(secondDeviceVk, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, &imageB, &allocationB,
                              &allocationSizeB, &memoryTypeIndexB, &memoryFdB);

        VkImage imageC;
        VkDeviceMemory allocationC;
        int memoryFdC;
        VkDeviceSize allocationSizeC;
        uint32_t memoryTypeIndexC;
        CreateBindExportImage(deviceVk, 1, 1, VK_FORMAT_R8G8B8A8_UNORM, &imageC, &allocationC,
                              &allocationSizeC, &memoryTypeIndexC, &memoryFdC);

        // Import TexA, TexB on device 3
        wgpu::Texture wrappedTexADevice3 = WrapVulkanImage(
            thirdDevice, &defaultDescriptor, memoryFdA, allocationSizeA, memoryTypeIndexA, {});

        wgpu::Texture wrappedTexBDevice3 = WrapVulkanImage(
            thirdDevice, &defaultDescriptor, memoryFdB, allocationSizeB, memoryTypeIndexB, {});

        // Clear TexA
        ClearImage(thirdDevice, wrappedTexADevice3,
                   {1 / 255.0f, 2 / 255.0f, 3 / 255.0f, 4 / 255.0f});

        // Copy A->B
        SimpleCopyTextureToTexture(thirdDevice, thirdDeviceQueue, wrappedTexADevice3,
                                   wrappedTexBDevice3);

        int signalFdTexBDevice3 = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
            thirdDevice.Get(), wrappedTexBDevice3.Get());
        IgnoreSignalSemaphore(thirdDevice, wrappedTexADevice3);

        // Import TexB, TexC on device 2
        memoryFdB = GetMemoryFd(secondDeviceVk, allocationB);
        wgpu::Texture wrappedTexBDevice2 =
            WrapVulkanImage(secondDevice, &defaultDescriptor, memoryFdB, allocationSizeB,
                            memoryTypeIndexB, {signalFdTexBDevice3});

        wgpu::Texture wrappedTexCDevice2 = WrapVulkanImage(
            secondDevice, &defaultDescriptor, memoryFdC, allocationSizeC, memoryTypeIndexC, {});

        // Copy B->C on device 2
        SimpleCopyTextureToTexture(secondDevice, secondDeviceQueue, wrappedTexBDevice2,
                                   wrappedTexCDevice2);

        int signalFdTexCDevice2 = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(
            secondDevice.Get(), wrappedTexCDevice2.Get());
        IgnoreSignalSemaphore(secondDevice, wrappedTexBDevice2);

        // Import TexC on device 1
        memoryFdC = GetMemoryFd(deviceVk, allocationC);
        wgpu::Texture wrappedTexCDevice1 =
            WrapVulkanImage(device, &defaultDescriptor, memoryFdC, allocationSizeC,
                            memoryTypeIndexC, {signalFdTexCDevice2});

        // Create TexD on device 1
        wgpu::Texture texD = device.CreateTexture(&defaultDescriptor);

        // Copy C->D on device 1
        SimpleCopyTextureToTexture(device, queue, wrappedTexCDevice1, texD);

        // Verify D matches clear color
        EXPECT_PIXEL_RGBA8_EQ(RGBA8(1, 2, 3, 4), texD, 0, 0);

        thirdDeviceVk->GetFencedDeleter()->DeleteWhenUnused(imageA);
        thirdDeviceVk->GetFencedDeleter()->DeleteWhenUnused(allocationA);
        secondDeviceVk->GetFencedDeleter()->DeleteWhenUnused(imageB);
        secondDeviceVk->GetFencedDeleter()->DeleteWhenUnused(allocationB);
        deviceVk->GetFencedDeleter()->DeleteWhenUnused(imageC);
        deviceVk->GetFencedDeleter()->DeleteWhenUnused(allocationC);

        IgnoreSignalSemaphore(device, wrappedTexCDevice1);
    }

    // Tests a larger image is preserved when importing
    // TODO(http://crbug.com/dawn/206): This fails on AMD
    TEST_P(VulkanImageWrappingUsageTests, LargerImage) {
        DAWN_SKIP_TEST_IF(UsesWire() || IsAMD());

        close(defaultFd);

        wgpu::TextureDescriptor descriptor;
        descriptor.dimension = wgpu::TextureDimension::e2D;
        descriptor.size.width = 640;
        descriptor.size.height = 480;
        descriptor.size.depth = 1;
        descriptor.arrayLayerCount = 1;
        descriptor.sampleCount = 1;
        descriptor.format = wgpu::TextureFormat::BGRA8Unorm;
        descriptor.mipLevelCount = 1;
        descriptor.usage = wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::CopySrc;

        // Fill memory with textures to trigger layout issues on AMD
        std::vector<wgpu::Texture> textures;
        for (int i = 0; i < 20; i++) {
            textures.push_back(device.CreateTexture(&descriptor));
        }

        wgpu::Queue secondDeviceQueue = secondDevice.GetDefaultQueue();

        // Make an image on |secondDevice|
        VkImage imageA;
        VkDeviceMemory allocationA;
        int memoryFdA;
        VkDeviceSize allocationSizeA;
        uint32_t memoryTypeIndexA;
        CreateBindExportImage(secondDeviceVk, 640, 480, VK_FORMAT_R8G8B8A8_UNORM, &imageA,
                              &allocationA, &allocationSizeA, &memoryTypeIndexA, &memoryFdA);

        // Import the image on |secondDevice|
        wgpu::Texture wrappedTexture = WrapVulkanImage(secondDevice, &descriptor, memoryFdA,
                                                       allocationSizeA, memoryTypeIndexA, {});

        // Draw a non-trivial picture
        uint32_t width = 640, height = 480, pixelSize = 4;
        uint32_t bytesPerRow = Align(width * pixelSize, kTextureBytesPerRowAlignment);
        std::vector<unsigned char> data(bytesPerRow * (height - 1) + width * pixelSize);

        for (uint32_t row = 0; row < height; row++) {
            for (uint32_t col = 0; col < width; col++) {
                float normRow = static_cast<float>(row) / height;
                float normCol = static_cast<float>(col) / width;
                float dist = sqrt(normRow * normRow + normCol * normCol) * 3;
                dist = dist - static_cast<int>(dist);
                data[4 * (row * width + col)] = static_cast<unsigned char>(dist * 255);
                data[4 * (row * width + col) + 1] = static_cast<unsigned char>(dist * 255);
                data[4 * (row * width + col) + 2] = static_cast<unsigned char>(dist * 255);
                data[4 * (row * width + col) + 3] = 255;
            }
        }

        // Write the picture
        {
            wgpu::Buffer copySrcBuffer = utils::CreateBufferFromData(
                secondDevice, data.data(), data.size(), wgpu::BufferUsage::CopySrc);
            wgpu::BufferCopyView copySrc =
                utils::CreateBufferCopyView(copySrcBuffer, 0, bytesPerRow, 0);
            wgpu::TextureCopyView copyDst =
                utils::CreateTextureCopyView(wrappedTexture, 0, 0, {0, 0, 0});
            wgpu::Extent3D copySize = {width, height, 1};

            wgpu::CommandEncoder encoder = secondDevice.CreateCommandEncoder();
            encoder.CopyBufferToTexture(&copySrc, &copyDst, &copySize);
            wgpu::CommandBuffer commands = encoder.Finish();
            secondDeviceQueue.Submit(1, &commands);
        }

        int signalFd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(secondDevice.Get(),
                                                                          wrappedTexture.Get());
        int memoryFd = GetMemoryFd(secondDeviceVk, allocationA);

        // Import the image on |device|
        wgpu::Texture nextWrappedTexture = WrapVulkanImage(
            device, &descriptor, memoryFd, allocationSizeA, memoryTypeIndexA, {signalFd});

        // Copy the image into a buffer for comparison
        wgpu::BufferDescriptor copyDesc;
        copyDesc.size = data.size();
        copyDesc.usage = wgpu::BufferUsage::CopySrc | wgpu::BufferUsage::CopyDst;
        wgpu::Buffer copyDstBuffer = device.CreateBuffer(&copyDesc);
        {
            wgpu::TextureCopyView copySrc =
                utils::CreateTextureCopyView(nextWrappedTexture, 0, 0, {0, 0, 0});
            wgpu::BufferCopyView copyDst =
                utils::CreateBufferCopyView(copyDstBuffer, 0, bytesPerRow, 0);

            wgpu::Extent3D copySize = {width, height, 1};

            wgpu::CommandEncoder encoder = device.CreateCommandEncoder();
            encoder.CopyTextureToBuffer(&copySrc, &copyDst, &copySize);
            wgpu::CommandBuffer commands = encoder.Finish();
            queue.Submit(1, &commands);
        }

        // Check the image is not corrupted on |device|
        EXPECT_BUFFER_U32_RANGE_EQ(reinterpret_cast<uint32_t*>(data.data()), copyDstBuffer, 0,
                                   data.size() / 4);

        IgnoreSignalSemaphore(device, nextWrappedTexture);
        secondDeviceVk->GetFencedDeleter()->DeleteWhenUnused(imageA);
        secondDeviceVk->GetFencedDeleter()->DeleteWhenUnused(allocationA);
    }

    DAWN_INSTANTIATE_TEST(VulkanImageWrappingValidationTests, VulkanBackend());
    DAWN_INSTANTIATE_TEST(VulkanImageWrappingUsageTests, VulkanBackend());

}}  // namespace dawn_native::vulkan
