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

// TODO(crbug.com/966500): Intel is disabled until upgrade is finished

namespace {

    class VulkanImageWrappingTestBase : public DawnTest {
      public:
        void TestSetUp() override {
            if (UsesWire() || IsIntel()) {
                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 device,
                                      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::WrapVulkanImageOpaqueFD(device.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 device, wgpu::Texture wrappedTexture) {
            int fd = dawn_native::vulkan::ExportSignalSemaphoreOpaqueFD(device.Get(),
                                                                        wrappedTexture.Get());
            ASSERT_NE(fd, -1);
            close(fd);
        }

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

}  // anonymous namespace

class VulkanImageWrappingValidationTests : public VulkanImageWrappingTestBase {
  public:
    void TestSetUp() override {
        VulkanImageWrappingTestBase::TestSetUp();
        if (UsesWire() || IsIntel()) {
            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() || IsIntel()) {
            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() || IsIntel());
    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() || IsIntel());
    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() || IsIntel());
    defaultDescriptor.nextInChain = this;

    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() || IsIntel());
    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() || IsIntel());
    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() || IsIntel());
    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() || IsIntel());
    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() || IsIntel());
    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() || IsIntel());
    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() || IsIntel());
    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 TestSetUp() override {
        VulkanImageWrappingTestBase::TestSetUp();
        if (UsesWire() || IsIntel()) {
            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() || IsIntel()) {
            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 device, 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 = device.CreateCommandEncoder();
        wgpu::RenderPassEncoder pass = encoder.BeginRenderPass(&renderPassDescriptor);
        pass.EndPass();

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

        wgpu::Queue queue = device.CreateQueue();
        queue.Submit(1, &commands);
    }

    // Submits a 1x1x1 copy from source to destination
    void SimpleCopyTextureToTexture(wgpu::Device device,
                                    wgpu::Queue queue,
                                    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 = device.CreateCommandEncoder();
        encoder.CopyTextureToTexture(&copySrc, &copyDst, &copySize);
        wgpu::CommandBuffer commands = encoder.Finish();

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

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

    // 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() || IsIntel());
    // 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() || IsIntel());

    // 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() || IsIntel());

    // 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() || IsIntel());

    // 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.CreateQueue();
    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() || IsIntel());

    // 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.rowPitch = 256;
    copyDst.imageHeight = 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() || IsIntel());

    // 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.CreateQueue();

    // 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.rowPitch = 256;
    copySrc.imageHeight = 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() || IsIntel());

    // 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() || IsIntel());

    // 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.CreateQueue();
    wgpu::Queue thirdDeviceQueue = thirdDevice.CreateQueue();

    // 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() || IsIntel() || 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.CreateQueue();

    // 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
    int width = 640, height = 480, pixelSize = 4;
    uint32_t rowPitch = Align(width * pixelSize, kTextureRowPitchAlignment);
    uint32_t size = rowPitch * (height - 1) + width * pixelSize;
    unsigned char data[size];
    for (int row = 0; row < height; row++) {
        for (int 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, size, wgpu::BufferUsage::CopySrc);
        wgpu::BufferCopyView copySrc = utils::CreateBufferCopyView(copySrcBuffer, 0, rowPitch, 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 = 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, rowPitch, 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), copyDstBuffer, 0, size / 4);

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

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