// Copyright (C) 2023 The Android Open Source Project
//
// 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 <log/log.h>

#include <atomic>
#include <thread>

#include "GfxstreamEnd2EndTestUtils.h"
#include "GfxstreamEnd2EndTests.h"
#include "gfxstream/Expected.h"
#include "shaders/blit_sampler2d_frag.h"
#include "shaders/fullscreen_triangle_with_uv_vert.h"

namespace gfxstream {
namespace tests {
namespace {

using namespace std::chrono_literals;
using testing::Eq;
using testing::Ge;
using testing::IsEmpty;
using testing::IsNull;
using testing::IsTrue;
using testing::Ne;
using testing::Not;
using testing::NotNull;

template <typename DurationType>
constexpr uint64_t AsVkTimeout(DurationType duration) {
    return static_cast<uint64_t>(std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count());
}

class GfxstreamEnd2EndVkTest : public GfxstreamEnd2EndTest {
   protected:
    // Gfxstream uses a vkQueueSubmit() to signal the VkFence and VkSemaphore used
    // in vkAcquireImageANDROID() calls. The guest is not aware of this and may try
    // to vkDestroyFence() and vkDestroySemaphore() (because the VkImage, VkFence,
    // and VkSemaphore may have been unused from the guest point of view) while the
    // host's command buffer is running. Gfxstream needs to ensure that it performs
    // the necessary tracking to not delete the VkFence and VkSemaphore while they
    // are in use on the host.
    void DoAcquireImageAndroidWithSync(bool withFence, bool withSemaphore) {
        auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
            GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());

        const uint32_t width = 32;
        const uint32_t height = 32;
        auto ahb = GFXSTREAM_ASSERT(ScopedAHardwareBuffer::Allocate(
            *mGralloc, width, height, GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM));

        const VkNativeBufferANDROID imageNativeBufferInfo = {
            .sType = VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID,
            .handle = mGralloc->getNativeHandle(ahb),
        };

        auto vkAcquireImageANDROID =
            PFN_vkAcquireImageANDROID(device->getProcAddr("vkAcquireImageANDROID"));
        ASSERT_THAT(vkAcquireImageANDROID, NotNull());

        const vkhpp::ImageCreateInfo imageCreateInfo = {
            .pNext = &imageNativeBufferInfo,
            .imageType = vkhpp::ImageType::e2D,
            .extent.width = width,
            .extent.height = height,
            .extent.depth = 1,
            .mipLevels = 1,
            .arrayLayers = 1,
            .format = vkhpp::Format::eR8G8B8A8Unorm,
            .tiling = vkhpp::ImageTiling::eOptimal,
            .initialLayout = vkhpp::ImageLayout::eUndefined,
            .usage = vkhpp::ImageUsageFlagBits::eSampled | vkhpp::ImageUsageFlagBits::eTransferDst |
                     vkhpp::ImageUsageFlagBits::eTransferSrc,
            .sharingMode = vkhpp::SharingMode::eExclusive,
            .samples = vkhpp::SampleCountFlagBits::e1,
        };
        auto image = device->createImageUnique(imageCreateInfo).value;

        vkhpp::MemoryRequirements imageMemoryRequirements{};
        device->getImageMemoryRequirements(*image, &imageMemoryRequirements);

        const uint32_t imageMemoryIndex = utils::getMemoryType(
            physicalDevice, imageMemoryRequirements, vkhpp::MemoryPropertyFlagBits::eDeviceLocal);
        ASSERT_THAT(imageMemoryIndex, Not(Eq(-1)));

        const vkhpp::MemoryAllocateInfo imageMemoryAllocateInfo = {
            .allocationSize = imageMemoryRequirements.size,
            .memoryTypeIndex = imageMemoryIndex,
        };

        auto imageMemory = device->allocateMemoryUnique(imageMemoryAllocateInfo).value;
        ASSERT_THAT(imageMemory, IsValidHandle());
        ASSERT_THAT(device->bindImageMemory(*image, *imageMemory, 0), IsVkSuccess());

        vkhpp::UniqueFence fence;
        if (withFence) {
            fence = device->createFenceUnique(vkhpp::FenceCreateInfo()).value;
        }

        vkhpp::UniqueSemaphore semaphore;
        if (withSemaphore) {
            semaphore = device->createSemaphoreUnique(vkhpp::SemaphoreCreateInfo()).value;
        }

        auto result = vkAcquireImageANDROID(*device, *image, -1, *semaphore, *fence);
        ASSERT_THAT(result, Eq(VK_SUCCESS));

        if (withFence) {
            fence.reset();
        }
        if (withSemaphore) {
            semaphore.reset();
        }
    }

    Result<Ok> DoCommandsImmediate(
        TypicalVkTestEnvironment& vk,
        const std::function<Result<Ok>(vkhpp::UniqueCommandBuffer&)>& func,
        const std::vector<vkhpp::UniqueSemaphore>& semaphores_wait = {},
        const std::vector<vkhpp::UniqueSemaphore>& semaphores_signal = {}) {
        const vkhpp::CommandPoolCreateInfo commandPoolCreateInfo = {
            .queueFamilyIndex = vk.queueFamilyIndex,
        };
        auto commandPool =
            GFXSTREAM_EXPECT_VKHPP_RV(vk.device->createCommandPoolUnique(commandPoolCreateInfo));

        const vkhpp::CommandBufferAllocateInfo commandBufferAllocateInfo = {
            .commandPool = *commandPool,
            .level = vkhpp::CommandBufferLevel::ePrimary,
            .commandBufferCount = 1,
        };
        auto commandBuffers = GFXSTREAM_EXPECT_VKHPP_RV(
            vk.device->allocateCommandBuffersUnique(commandBufferAllocateInfo));
        auto commandBuffer = std::move(commandBuffers[0]);

        const vkhpp::CommandBufferBeginInfo commandBufferBeginInfo = {
            .flags = vkhpp::CommandBufferUsageFlagBits::eOneTimeSubmit,
        };
        commandBuffer->begin(commandBufferBeginInfo);
        GFXSTREAM_EXPECT(func(commandBuffer));
        commandBuffer->end();

        std::vector<vkhpp::CommandBuffer> commandBufferHandles;
        commandBufferHandles.push_back(*commandBuffer);

        std::vector<vkhpp::Semaphore> semaphoreHandlesWait;
        semaphoreHandlesWait.reserve(semaphores_wait.size());
        for (const auto& s : semaphores_wait) {
            semaphoreHandlesWait.emplace_back(*s);
        }

        std::vector<vkhpp::Semaphore> semaphoreHandlesSignal;
        semaphoreHandlesSignal.reserve(semaphores_signal.size());
        for (const auto& s : semaphores_signal) {
            semaphoreHandlesSignal.emplace_back(*s);
        }

        vkhpp::SubmitInfo submitInfo = {
            .commandBufferCount = static_cast<uint32_t>(commandBufferHandles.size()),
            .pCommandBuffers = commandBufferHandles.data(),
        };
        if (!semaphoreHandlesWait.empty()) {
            submitInfo.waitSemaphoreCount = static_cast<uint32_t>(semaphoreHandlesWait.size());
            submitInfo.pWaitSemaphores = semaphoreHandlesWait.data();
        }
        if (!semaphoreHandlesSignal.empty()) {
            submitInfo.signalSemaphoreCount = static_cast<uint32_t>(semaphoreHandlesSignal.size());
            submitInfo.pSignalSemaphores = semaphoreHandlesSignal.data();
        }
        vk.queue.submit(submitInfo);
        vk.queue.waitIdle();
        return Ok{};
    }

    struct BufferWithMemory {
        vkhpp::UniqueBuffer buffer;
        vkhpp::UniqueDeviceMemory bufferMemory;
    };
    Result<BufferWithMemory> CreateBuffer(TypicalVkTestEnvironment& vk,
                                          vkhpp::DeviceSize bufferSize,
                                          vkhpp::BufferUsageFlags bufferUsages,
                                          vkhpp::MemoryPropertyFlags bufferMemoryProperties,
                                          const uint8_t* data = nullptr,
                                          vkhpp::DeviceSize dataSize = 0) {
        const vkhpp::BufferCreateInfo bufferCreateInfo = {
            .size = static_cast<VkDeviceSize>(bufferSize),
            .usage = bufferUsages,
            .sharingMode = vkhpp::SharingMode::eExclusive,
        };
        auto buffer = GFXSTREAM_EXPECT_VKHPP_RV(vk.device->createBufferUnique(bufferCreateInfo));

        vkhpp::MemoryRequirements bufferMemoryRequirements{};
        vk.device->getBufferMemoryRequirements(*buffer, &bufferMemoryRequirements);

        const auto bufferMemoryTypeIndex = utils::getMemoryType(
            vk.physicalDevice, bufferMemoryRequirements, bufferMemoryProperties);

        const vkhpp::MemoryAllocateInfo bufferMemoryAllocateInfo = {
            .allocationSize = bufferMemoryRequirements.size,
            .memoryTypeIndex = bufferMemoryTypeIndex,
        };
        auto bufferMemory =
            GFXSTREAM_EXPECT_VKHPP_RV(vk.device->allocateMemoryUnique(bufferMemoryAllocateInfo));

        GFXSTREAM_EXPECT_VKHPP_RESULT(vk.device->bindBufferMemory(*buffer, *bufferMemory, 0));

        if (data != nullptr) {
            if (!(bufferUsages & vkhpp::BufferUsageFlagBits::eTransferDst)) {
                return gfxstream::unexpected(
                    "Must request transfer dst usage when creating buffer with data");
            }
            if (!(bufferMemoryProperties & vkhpp::MemoryPropertyFlagBits::eHostVisible)) {
                return gfxstream::unexpected(
                    "Must request host visible mem property when creating buffer with data");
            }

            void* mapped =
                GFXSTREAM_EXPECT_VKHPP_RV(vk.device->mapMemory(*bufferMemory, 0, bufferSize));

            std::memcpy(mapped, data, dataSize);

            if (!(bufferMemoryProperties & vkhpp::MemoryPropertyFlagBits::eHostVisible)) {
                vk.device->flushMappedMemoryRanges(vkhpp::MappedMemoryRange{
                    .memory = *bufferMemory,
                    .offset = 0,
                    .size = VK_WHOLE_SIZE,
                });
            }

            vk.device->unmapMemory(*bufferMemory);
        }

        return BufferWithMemory{
            .buffer = std::move(buffer),
            .bufferMemory = std::move(bufferMemory),
        };
    }

    struct ImageWithMemory {
        std::optional<vkhpp::UniqueSamplerYcbcrConversion> imageSamplerConversion;
        vkhpp::UniqueSampler imageSampler;
        vkhpp::UniqueDeviceMemory imageMemory;
        vkhpp::UniqueImage image;
        vkhpp::UniqueImageView imageView;
    };
    Result<ImageWithMemory> CreateImageWithAhb(TypicalVkTestEnvironment& vk,
                                               const ScopedAHardwareBuffer& ahb,
                                               const vkhpp::ImageUsageFlags usages,
                                               const vkhpp::ImageLayout layout) {
        const auto ahbHandle = mGralloc->getNativeHandle(ahb);
        if (ahbHandle == nullptr) {
            return gfxstream::unexpected("Failed to query native handle.");
        }
        const auto ahbFormat = mGralloc->getFormat(ahb);
        const bool ahbIsYuv = ahbFormat == GFXSTREAM_AHB_FORMAT_YV12 ||
                              ahbFormat == GFXSTREAM_AHB_FORMAT_Y8Cb8Cr8_420;

        auto vkGetAndroidHardwareBufferPropertiesANDROID =
            reinterpret_cast<PFN_vkGetAndroidHardwareBufferPropertiesANDROID>(
                vk.device->getProcAddr("vkGetAndroidHardwareBufferPropertiesANDROID"));
        if (vkGetAndroidHardwareBufferPropertiesANDROID == nullptr) {
            return gfxstream::unexpected(
                "Failed to query vkGetAndroidHardwareBufferPropertiesANDROID().");
        }
        VkAndroidHardwareBufferFormatPropertiesANDROID ahbFormatProperties = {
            .sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_FORMAT_PROPERTIES_ANDROID,
            .pNext = nullptr,
        };
        VkAndroidHardwareBufferPropertiesANDROID ahbProperties = {
            .sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID,
            .pNext = &ahbFormatProperties,
        };
        if (vkGetAndroidHardwareBufferPropertiesANDROID(*vk.device, ahb, &ahbProperties) !=
            VK_SUCCESS) {
            return gfxstream::unexpected("Failed to query ahb properties.");
        }

        const VkExternalFormatANDROID externalFormat = {
            .sType = VK_STRUCTURE_TYPE_EXTERNAL_FORMAT_ANDROID,
            .externalFormat = ahbFormatProperties.externalFormat,
        };

        std::optional<vkhpp::UniqueSamplerYcbcrConversion> imageSamplerConversion;
        std::optional<vkhpp::SamplerYcbcrConversionInfo> samplerConversionInfo;
        if (ahbIsYuv) {
            const vkhpp::SamplerYcbcrConversionCreateInfo conversionCreateInfo = {
                .pNext = &externalFormat,
                .format = static_cast<vkhpp::Format>(ahbFormatProperties.format),
                .ycbcrModel = static_cast<vkhpp::SamplerYcbcrModelConversion>(
                    ahbFormatProperties.suggestedYcbcrModel),
                .ycbcrRange =
                    static_cast<vkhpp::SamplerYcbcrRange>(ahbFormatProperties.suggestedYcbcrRange),
                .components =
                    {
                        .r = static_cast<vkhpp::ComponentSwizzle>(
                            ahbFormatProperties.samplerYcbcrConversionComponents.r),
                        .g = static_cast<vkhpp::ComponentSwizzle>(
                            ahbFormatProperties.samplerYcbcrConversionComponents.g),
                        .b = static_cast<vkhpp::ComponentSwizzle>(
                            ahbFormatProperties.samplerYcbcrConversionComponents.b),
                        .a = static_cast<vkhpp::ComponentSwizzle>(
                            ahbFormatProperties.samplerYcbcrConversionComponents.a),
                    },
                .xChromaOffset =
                    static_cast<vkhpp::ChromaLocation>(ahbFormatProperties.suggestedXChromaOffset),
                .yChromaOffset =
                    static_cast<vkhpp::ChromaLocation>(ahbFormatProperties.suggestedYChromaOffset),
                .chromaFilter = vkhpp::Filter::eNearest,
                .forceExplicitReconstruction = VK_FALSE,
            };
            imageSamplerConversion = GFXSTREAM_EXPECT_VKHPP_RV(
                vk.device->createSamplerYcbcrConversionUnique(conversionCreateInfo));

            samplerConversionInfo = vkhpp::SamplerYcbcrConversionInfo{
                .conversion = **imageSamplerConversion,
            };
        }
        const vkhpp::SamplerCreateInfo samplerCreateInfo = {
            .pNext = ahbIsYuv ? &samplerConversionInfo : nullptr,
            .magFilter = vkhpp::Filter::eNearest,
            .minFilter = vkhpp::Filter::eNearest,
            .mipmapMode = vkhpp::SamplerMipmapMode::eNearest,
            .addressModeU = vkhpp::SamplerAddressMode::eClampToEdge,
            .addressModeV = vkhpp::SamplerAddressMode::eClampToEdge,
            .addressModeW = vkhpp::SamplerAddressMode::eClampToEdge,
            .mipLodBias = 0.0f,
            .anisotropyEnable = VK_FALSE,
            .maxAnisotropy = 1.0f,
            .compareEnable = VK_FALSE,
            .compareOp = vkhpp::CompareOp::eLessOrEqual,
            .minLod = 0.0f,
            .maxLod = 0.0f,
            .borderColor = vkhpp::BorderColor::eIntTransparentBlack,
            .unnormalizedCoordinates = VK_FALSE,
        };
        auto imageSampler =
            GFXSTREAM_EXPECT_VKHPP_RV(vk.device->createSamplerUnique(samplerCreateInfo));

        const VkExternalMemoryImageCreateInfo externalMemoryImageCreateInfo = {
            .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO,
            .pNext = &externalFormat,
            .handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID,
        };
        const vkhpp::ImageCreateInfo imageCreateInfo = {
            .pNext = &externalMemoryImageCreateInfo,
            .imageType = vkhpp::ImageType::e2D,
            .format = static_cast<vkhpp::Format>(ahbFormatProperties.format),
            .extent =
                {
                    .width = mGralloc->getWidth(ahb),
                    .height = mGralloc->getHeight(ahb),
                    .depth = 1,
                },
            .mipLevels = 1,
            .arrayLayers = 1,
            .samples = vkhpp::SampleCountFlagBits::e1,
            .tiling = vkhpp::ImageTiling::eOptimal,
            .usage = usages,
            .sharingMode = vkhpp::SharingMode::eExclusive,
            .initialLayout = vkhpp::ImageLayout::eUndefined,
        };
        auto image = GFXSTREAM_EXPECT_VKHPP_RV(vk.device->createImageUnique(imageCreateInfo));

        const vkhpp::MemoryRequirements imageMemoryRequirements = {
            .size = ahbProperties.allocationSize,
            .alignment = 0,
            .memoryTypeBits = ahbProperties.memoryTypeBits,
        };
        const uint32_t imageMemoryIndex =
            utils::getMemoryType(vk.physicalDevice, imageMemoryRequirements,
                                 vkhpp::MemoryPropertyFlagBits::eDeviceLocal);

        const vkhpp::ImportAndroidHardwareBufferInfoANDROID importAhbInfo = {
            .buffer = ahb,
        };
        const vkhpp::MemoryDedicatedAllocateInfo importMemoryDedicatedInfo = {
            .pNext = &importAhbInfo,
            .image = *image,
        };
        const vkhpp::MemoryAllocateInfo imageMemoryAllocateInfo = {
            .pNext = &importMemoryDedicatedInfo,
            .allocationSize = imageMemoryRequirements.size,
            .memoryTypeIndex = imageMemoryIndex,
        };
        auto imageMemory =
            GFXSTREAM_EXPECT_VKHPP_RV(vk.device->allocateMemoryUnique(imageMemoryAllocateInfo));
        vk.device->bindImageMemory(*image, *imageMemory, 0);

        const vkhpp::ImageViewCreateInfo imageViewCreateInfo = {
            .pNext = &samplerConversionInfo,
            .image = *image,
            .viewType = vkhpp::ImageViewType::e2D,
            .format = static_cast<vkhpp::Format>(ahbFormatProperties.format),
            .components =
                {
                    .r = vkhpp::ComponentSwizzle::eIdentity,
                    .g = vkhpp::ComponentSwizzle::eIdentity,
                    .b = vkhpp::ComponentSwizzle::eIdentity,
                    .a = vkhpp::ComponentSwizzle::eIdentity,
                },
            .subresourceRange =
                {
                    .aspectMask = vkhpp::ImageAspectFlagBits::eColor,
                    .baseMipLevel = 0,
                    .levelCount = 1,
                    .baseArrayLayer = 0,
                    .layerCount = 1,
                },
        };
        auto imageView =
            GFXSTREAM_EXPECT_VKHPP_RV(vk.device->createImageViewUnique(imageViewCreateInfo));

        GFXSTREAM_EXPECT(DoCommandsImmediate(vk, [&](vkhpp::UniqueCommandBuffer& cmd) {
            const std::vector<vkhpp::ImageMemoryBarrier> imageMemoryBarriers = {
                vkhpp::ImageMemoryBarrier{
                    .srcAccessMask = {},
                    .dstAccessMask = vkhpp::AccessFlagBits::eTransferWrite,
                    .oldLayout = vkhpp::ImageLayout::eUndefined,
                    .newLayout = layout,
                    .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
                    .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
                    .image = *image,
                    .subresourceRange =
                        {
                            .aspectMask = vkhpp::ImageAspectFlagBits::eColor,
                            .baseMipLevel = 0,
                            .levelCount = 1,
                            .baseArrayLayer = 0,
                            .layerCount = 1,
                        },

                },
            };
            cmd->pipelineBarrier(
                /*srcStageMask=*/vkhpp::PipelineStageFlagBits::eAllCommands,
                /*dstStageMask=*/vkhpp::PipelineStageFlagBits::eAllCommands,
                /*dependencyFlags=*/{},
                /*memoryBarriers=*/{},
                /*bufferMemoryBarriers=*/{},
                /*imageMemoryBarriers=*/imageMemoryBarriers);
            return Ok{};
        }));

        return ImageWithMemory{
            .imageSamplerConversion = std::move(imageSamplerConversion),
            .imageSampler = std::move(imageSampler),
            .imageMemory = std::move(imageMemory),
            .image = std::move(image),
            .imageView = std::move(imageView),
        };
    }

    Result<ImageWithMemory> CreateImage(TypicalVkTestEnvironment& vk, uint32_t width,
                                        uint32_t height, vkhpp::Format format,
                                        vkhpp::ImageUsageFlags usages,
                                        vkhpp::MemoryPropertyFlags memoryProperties,
                                        vkhpp::ImageLayout returnedLayout) {
        const vkhpp::ImageCreateInfo imageCreateInfo = {
            .imageType = vkhpp::ImageType::e2D,
            .format = format,
            .extent =
                {
                    .width = width,
                    .height = height,
                    .depth = 1,
                },
            .mipLevels = 1,
            .arrayLayers = 1,
            .samples = vkhpp::SampleCountFlagBits::e1,
            .tiling = vkhpp::ImageTiling::eOptimal,
            .usage = usages,
            .sharingMode = vkhpp::SharingMode::eExclusive,
            .initialLayout = vkhpp::ImageLayout::eUndefined,
        };
        auto image = GFXSTREAM_EXPECT_VKHPP_RV(vk.device->createImageUnique(imageCreateInfo));

        const auto memoryRequirements = vk.device->getImageMemoryRequirements(*image);
        const uint32_t memoryIndex =
            utils::getMemoryType(vk.physicalDevice, memoryRequirements, memoryProperties);

        const vkhpp::MemoryAllocateInfo imageMemoryAllocateInfo = {
            .allocationSize = memoryRequirements.size,
            .memoryTypeIndex = memoryIndex,
        };
        auto imageMemory =
            GFXSTREAM_EXPECT_VKHPP_RV(vk.device->allocateMemoryUnique(imageMemoryAllocateInfo));

        vk.device->bindImageMemory(*image, *imageMemory, 0);

        const vkhpp::ImageViewCreateInfo imageViewCreateInfo = {
            .image = *image,
            .viewType = vkhpp::ImageViewType::e2D,
            .format = format,
            .components =
                {
                    .r = vkhpp::ComponentSwizzle::eIdentity,
                    .g = vkhpp::ComponentSwizzle::eIdentity,
                    .b = vkhpp::ComponentSwizzle::eIdentity,
                    .a = vkhpp::ComponentSwizzle::eIdentity,
                },
            .subresourceRange =
                {
                    .aspectMask = vkhpp::ImageAspectFlagBits::eColor,
                    .baseMipLevel = 0,
                    .levelCount = 1,
                    .baseArrayLayer = 0,
                    .layerCount = 1,
                },
        };
        auto imageView =
            GFXSTREAM_EXPECT_VKHPP_RV(vk.device->createImageViewUnique(imageViewCreateInfo));

        GFXSTREAM_EXPECT(DoCommandsImmediate(vk, [&](vkhpp::UniqueCommandBuffer& cmd) {
            const std::vector<vkhpp::ImageMemoryBarrier> imageMemoryBarriers = {
                vkhpp::ImageMemoryBarrier{
                    .srcAccessMask = {},
                    .dstAccessMask = vkhpp::AccessFlagBits::eTransferWrite,
                    .oldLayout = vkhpp::ImageLayout::eUndefined,
                    .newLayout = returnedLayout,
                    .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
                    .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
                    .image = *image,
                    .subresourceRange =
                        {
                            .aspectMask = vkhpp::ImageAspectFlagBits::eColor,
                            .baseMipLevel = 0,
                            .levelCount = 1,
                            .baseArrayLayer = 0,
                            .layerCount = 1,
                        },
                },
            };
            cmd->pipelineBarrier(
                /*srcStageMask=*/vkhpp::PipelineStageFlagBits::eAllCommands,
                /*dstStageMask=*/vkhpp::PipelineStageFlagBits::eAllCommands,
                /*dependencyFlags=*/{},
                /*memoryBarriers=*/{},
                /*bufferMemoryBarriers=*/{},
                /*imageMemoryBarriers=*/imageMemoryBarriers);

            return Ok{};
        }));

        return ImageWithMemory{
            .image = std::move(image),
            .imageMemory = std::move(imageMemory),
            .imageView = std::move(imageView),
        };
    }

    struct FramebufferWithAttachments {
        std::optional<ImageWithMemory> colorAttachment;
        std::optional<ImageWithMemory> depthAttachment;
        vkhpp::UniqueRenderPass renderpass;
        vkhpp::UniqueFramebuffer framebuffer;
    };
    Result<FramebufferWithAttachments> CreateFramebuffer(
        TypicalVkTestEnvironment& vk, uint32_t width, uint32_t height,
        vkhpp::Format colorAttachmentFormat = vkhpp::Format::eUndefined,
        vkhpp::Format depthAttachmentFormat = vkhpp::Format::eUndefined) {
        std::optional<ImageWithMemory> colorAttachment;
        if (colorAttachmentFormat != vkhpp::Format::eUndefined) {
            colorAttachment =
                GFXSTREAM_EXPECT(CreateImage(vk, width, height, colorAttachmentFormat,
                                             vkhpp::ImageUsageFlagBits::eColorAttachment |
                                                 vkhpp::ImageUsageFlagBits::eTransferSrc,
                                             vkhpp::MemoryPropertyFlagBits::eDeviceLocal,
                                             vkhpp::ImageLayout::eColorAttachmentOptimal));
        }

        std::optional<ImageWithMemory> depthAttachment;
        if (depthAttachmentFormat != vkhpp::Format::eUndefined) {
            depthAttachment =
                GFXSTREAM_EXPECT(CreateImage(vk, width, height, depthAttachmentFormat,
                                             vkhpp::ImageUsageFlagBits::eDepthStencilAttachment |
                                                 vkhpp::ImageUsageFlagBits::eTransferSrc,
                                             vkhpp::MemoryPropertyFlagBits::eDeviceLocal,
                                             vkhpp::ImageLayout::eDepthStencilAttachmentOptimal));
        }

        std::vector<vkhpp::AttachmentDescription> attachments;

        std::optional<vkhpp::AttachmentReference> colorAttachmentReference;
        if (colorAttachmentFormat != vkhpp::Format::eUndefined) {
            attachments.push_back(vkhpp::AttachmentDescription{
                .format = colorAttachmentFormat,
                .samples = vkhpp::SampleCountFlagBits::e1,
                .loadOp = vkhpp::AttachmentLoadOp::eClear,
                .storeOp = vkhpp::AttachmentStoreOp::eStore,
                .stencilLoadOp = vkhpp::AttachmentLoadOp::eClear,
                .stencilStoreOp = vkhpp::AttachmentStoreOp::eStore,
                .initialLayout = vkhpp::ImageLayout::eColorAttachmentOptimal,
                .finalLayout = vkhpp::ImageLayout::eColorAttachmentOptimal,
            });

            colorAttachmentReference = vkhpp::AttachmentReference{
                .attachment = static_cast<uint32_t>(attachments.size() - 1),
                .layout = vkhpp::ImageLayout::eColorAttachmentOptimal,
            };
        }

        std::optional<vkhpp::AttachmentReference> depthAttachmentReference;
        if (depthAttachmentFormat != vkhpp::Format::eUndefined) {
            attachments.push_back(vkhpp::AttachmentDescription{
                .format = depthAttachmentFormat,
                .samples = vkhpp::SampleCountFlagBits::e1,
                .loadOp = vkhpp::AttachmentLoadOp::eClear,
                .storeOp = vkhpp::AttachmentStoreOp::eStore,
                .stencilLoadOp = vkhpp::AttachmentLoadOp::eClear,
                .stencilStoreOp = vkhpp::AttachmentStoreOp::eStore,
                .initialLayout = vkhpp::ImageLayout::eColorAttachmentOptimal,
                .finalLayout = vkhpp::ImageLayout::eColorAttachmentOptimal,
            });

            depthAttachmentReference = vkhpp::AttachmentReference{
                .attachment = static_cast<uint32_t>(attachments.size() - 1),
                .layout = vkhpp::ImageLayout::eDepthStencilAttachmentOptimal,
            };
        }

        vkhpp::SubpassDependency dependency = {
            .srcSubpass = 0,
            .dstSubpass = 0,
            .srcStageMask = {},
            .dstStageMask = vkhpp::PipelineStageFlagBits::eFragmentShader,
            .srcAccessMask = {},
            .dstAccessMask = vkhpp::AccessFlagBits::eInputAttachmentRead,
            .dependencyFlags = vkhpp::DependencyFlagBits::eByRegion,
        };
        if (colorAttachmentFormat != vkhpp::Format::eUndefined) {
            dependency.srcStageMask |= vkhpp::PipelineStageFlagBits::eColorAttachmentOutput;
            dependency.dstStageMask |= vkhpp::PipelineStageFlagBits::eColorAttachmentOutput;
            dependency.srcAccessMask |= vkhpp::AccessFlagBits::eColorAttachmentWrite;
        }
        if (depthAttachmentFormat != vkhpp::Format::eUndefined) {
            dependency.srcStageMask |= vkhpp::PipelineStageFlagBits::eColorAttachmentOutput;
            dependency.dstStageMask |= vkhpp::PipelineStageFlagBits::eColorAttachmentOutput;
            dependency.srcAccessMask |= vkhpp::AccessFlagBits::eColorAttachmentWrite;
        }

        vkhpp::SubpassDescription subpass = {
            .pipelineBindPoint = vkhpp::PipelineBindPoint::eGraphics,
            .inputAttachmentCount = 0,
            .pInputAttachments = nullptr,
            .colorAttachmentCount = 0,
            .pColorAttachments = nullptr,
            .pResolveAttachments = nullptr,
            .pDepthStencilAttachment = nullptr,
            .pPreserveAttachments = nullptr,
        };
        if (colorAttachmentFormat != vkhpp::Format::eUndefined) {
            subpass.colorAttachmentCount = 1;
            subpass.pColorAttachments = &*colorAttachmentReference;
        }
        if (depthAttachmentFormat != vkhpp::Format::eUndefined) {
            subpass.pDepthStencilAttachment = &*depthAttachmentReference;
        }

        const vkhpp::RenderPassCreateInfo renderpassCreateInfo = {
            .attachmentCount = static_cast<uint32_t>(attachments.size()),
            .pAttachments = attachments.data(),
            .subpassCount = 1,
            .pSubpasses = &subpass,
            .dependencyCount = 1,
            .pDependencies = &dependency,
        };
        auto renderpass =
            GFXSTREAM_EXPECT_VKHPP_RV(vk.device->createRenderPassUnique(renderpassCreateInfo));

        std::vector<vkhpp::ImageView> framebufferAttachments;
        if (colorAttachment) {
            framebufferAttachments.push_back(*colorAttachment->imageView);
        }
        if (depthAttachment) {
            framebufferAttachments.push_back(*depthAttachment->imageView);
        }
        const vkhpp::FramebufferCreateInfo framebufferCreateInfo = {
            .renderPass = *renderpass,
            .attachmentCount = static_cast<uint32_t>(framebufferAttachments.size()),
            .pAttachments = framebufferAttachments.data(),
            .width = width,
            .height = height,
            .layers = 1,
        };
        auto framebuffer =
            GFXSTREAM_EXPECT_VKHPP_RV(vk.device->createFramebufferUnique(framebufferCreateInfo));

        return FramebufferWithAttachments{
            .colorAttachment = std::move(colorAttachment),
            .depthAttachment = std::move(depthAttachment),
            .renderpass = std::move(renderpass),
            .framebuffer = std::move(framebuffer),
        };
    }

    struct DescriptorContents {
        uint32_t binding = 0;
        struct Image {
            vkhpp::ImageView imageView;
            vkhpp::ImageLayout imageLayout;
            vkhpp::Sampler imageSampler;
        };
        std::optional<Image> image;
    };
    struct DescriptorSetBundle {
        vkhpp::UniqueDescriptorPool pool;
        vkhpp::UniqueDescriptorSetLayout layout;
        vkhpp::UniqueDescriptorSet ds;
    };
    Result<DescriptorSetBundle> CreateDescriptorSet(
        TypicalVkTestEnvironment& vk,
        const std::vector<vkhpp::DescriptorSetLayoutBinding>& bindings,
        const std::vector<DescriptorContents> contents) {
        std::unordered_map<vkhpp::DescriptorType, uint32_t> descriptorTypeToSizes;
        for (const auto& binding : bindings) {
            descriptorTypeToSizes[binding.descriptorType] += binding.descriptorCount;
        }
        std::vector<vkhpp::DescriptorPoolSize> descriptorPoolSizes;
        for (const auto& [descriptorType, descriptorCount] : descriptorTypeToSizes) {
            descriptorPoolSizes.push_back(vkhpp::DescriptorPoolSize{
                .type = descriptorType,
                .descriptorCount = descriptorCount,
            });
        }
        const vkhpp::DescriptorPoolCreateInfo descriptorPoolCreateInfo = {
            .flags = vkhpp::DescriptorPoolCreateFlagBits::eFreeDescriptorSet,
            .maxSets = 1,
            .poolSizeCount = static_cast<uint32_t>(descriptorPoolSizes.size()),
            .pPoolSizes = descriptorPoolSizes.data(),
        };
        auto descriptorSetPool = GFXSTREAM_EXPECT_VKHPP_RV(
            vk.device->createDescriptorPoolUnique(descriptorPoolCreateInfo));

        const vkhpp::DescriptorSetLayoutCreateInfo descriptorSetLayoutCreateInfo = {
            .bindingCount = static_cast<uint32_t>(bindings.size()),
            .pBindings = bindings.data(),
        };
        auto descriptorSetLayout = GFXSTREAM_EXPECT_VKHPP_RV(
            vk.device->createDescriptorSetLayoutUnique(descriptorSetLayoutCreateInfo));

        const vkhpp::DescriptorSetLayout descriptorSetLayoutHandle = *descriptorSetLayout;
        const vkhpp::DescriptorSetAllocateInfo descriptorSetAllocateInfo = {
            .descriptorPool = *descriptorSetPool,
            .descriptorSetCount = 1,
            .pSetLayouts = &descriptorSetLayoutHandle,
        };
        auto descriptorSets = GFXSTREAM_EXPECT_VKHPP_RV(
            vk.device->allocateDescriptorSetsUnique(descriptorSetAllocateInfo));
        auto descriptorSet(std::move(descriptorSets[0]));

        std::vector<std::unique_ptr<vkhpp::DescriptorImageInfo>> descriptorImageInfos;
        std::vector<vkhpp::WriteDescriptorSet> descriptorSetWrites;
        for (const auto& content : contents) {
            if (content.image) {
                descriptorImageInfos.emplace_back(new vkhpp::DescriptorImageInfo{
                    .sampler = content.image->imageSampler,
                    .imageView = content.image->imageView,
                    .imageLayout = content.image->imageLayout,
                });
                descriptorSetWrites.emplace_back(vkhpp::WriteDescriptorSet{
                    .dstSet = *descriptorSet,
                    .dstBinding = content.binding,
                    .dstArrayElement = 0,
                    .descriptorCount = 1,
                    .descriptorType = vkhpp::DescriptorType::eCombinedImageSampler,
                    .pImageInfo = descriptorImageInfos.back().get(),
                });
            } else {
                return gfxstream::unexpected("Unhandled descriptor type");
                ;
            }
        }
        vk.device->updateDescriptorSets(descriptorSetWrites, {});

        return DescriptorSetBundle{
            .pool = std::move(descriptorSetPool),
            .layout = std::move(descriptorSetLayout),
            .ds = std::move(descriptorSet),
        };
    }

    struct PipelineParams {
        std::vector<uint32_t> vert;
        std::vector<uint32_t> frag;
        std::vector<DescriptorSetBundle*> descriptorSets;
        const FramebufferWithAttachments* framebuffer = nullptr;
    };
    struct PipelineBundle {
        vkhpp::UniqueShaderModule vert;
        vkhpp::UniqueShaderModule frag;
        vkhpp::UniquePipelineLayout pipelineLayout;
        vkhpp::UniquePipeline pipeline;
    };
    Result<PipelineBundle> CreatePipeline(TypicalVkTestEnvironment& vk,
                                          const PipelineParams& params) {
        const vkhpp::ShaderModuleCreateInfo vertShaderCreateInfo = {
            .codeSize = params.vert.size() * sizeof(uint32_t),
            .pCode = params.vert.data(),
        };
        auto vertShaderModule =
            GFXSTREAM_EXPECT_VKHPP_RV(vk.device->createShaderModuleUnique(vertShaderCreateInfo));

        const vkhpp::ShaderModuleCreateInfo fragShaderCreateInfo = {
            .codeSize = params.frag.size() * sizeof(uint32_t),
            .pCode = params.frag.data(),
        };
        auto fragShaderModule =
            GFXSTREAM_EXPECT_VKHPP_RV(vk.device->createShaderModuleUnique(fragShaderCreateInfo));

        const std::vector<vkhpp::PipelineShaderStageCreateInfo> pipelineStages = {
            vkhpp::PipelineShaderStageCreateInfo{
                .stage = vkhpp::ShaderStageFlagBits::eVertex,
                .module = *vertShaderModule,
                .pName = "main",
            },
            vkhpp::PipelineShaderStageCreateInfo{
                .stage = vkhpp::ShaderStageFlagBits::eFragment,
                .module = *fragShaderModule,
                .pName = "main",
            },
        };

        std::vector<vkhpp::DescriptorSetLayout> descriptorSetLayoutHandles;
        for (const auto* descriptorSet : params.descriptorSets) {
            descriptorSetLayoutHandles.push_back(*descriptorSet->layout);
        }
        const vkhpp::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
            .setLayoutCount = static_cast<uint32_t>(descriptorSetLayoutHandles.size()),
            .pSetLayouts = descriptorSetLayoutHandles.data(),
        };
        auto pipelineLayout = GFXSTREAM_EXPECT_VKHPP_RV(
            vk.device->createPipelineLayoutUnique(pipelineLayoutCreateInfo));

        const vkhpp::PipelineVertexInputStateCreateInfo pipelineVertexInputStateCreateInfo = {};
        const vkhpp::PipelineInputAssemblyStateCreateInfo pipelineInputAssemblyStateCreateInfo = {
            .topology = vkhpp::PrimitiveTopology::eTriangleList,
        };
        const vkhpp::PipelineViewportStateCreateInfo pipelineViewportStateCreateInfo = {
            .viewportCount = 1,
            .pViewports = nullptr,
            .scissorCount = 1,
            .pScissors = nullptr,
        };
        const vkhpp::PipelineRasterizationStateCreateInfo pipelineRasterStateCreateInfo = {
            .depthClampEnable = VK_FALSE,
            .rasterizerDiscardEnable = VK_FALSE,
            .polygonMode = vkhpp::PolygonMode::eFill,
            .cullMode = {},
            .frontFace = vkhpp::FrontFace::eCounterClockwise,
            .depthBiasEnable = VK_FALSE,
            .depthBiasConstantFactor = 0.0f,
            .depthBiasClamp = 0.0f,
            .depthBiasSlopeFactor = 0.0f,
            .lineWidth = 1.0f,
        };
        const vkhpp::SampleMask pipelineSampleMask = 65535;
        const vkhpp::PipelineMultisampleStateCreateInfo pipelineMultisampleStateCreateInfo = {
            .rasterizationSamples = vkhpp::SampleCountFlagBits::e1,
            .sampleShadingEnable = VK_FALSE,
            .minSampleShading = 1.0f,
            .pSampleMask = &pipelineSampleMask,
            .alphaToCoverageEnable = VK_FALSE,
            .alphaToOneEnable = VK_FALSE,
        };
        const vkhpp::PipelineDepthStencilStateCreateInfo pipelineDepthStencilStateCreateInfo = {
            .depthTestEnable = VK_FALSE,
            .depthWriteEnable = VK_FALSE,
            .depthCompareOp = vkhpp::CompareOp::eLess,
            .depthBoundsTestEnable = VK_FALSE,
            .stencilTestEnable = VK_FALSE,
            .front =
                {
                    .failOp = vkhpp::StencilOp::eKeep,
                    .passOp = vkhpp::StencilOp::eKeep,
                    .depthFailOp = vkhpp::StencilOp::eKeep,
                    .compareOp = vkhpp::CompareOp::eAlways,
                    .compareMask = 0,
                    .writeMask = 0,
                    .reference = 0,
                },
            .back =
                {
                    .failOp = vkhpp::StencilOp::eKeep,
                    .passOp = vkhpp::StencilOp::eKeep,
                    .depthFailOp = vkhpp::StencilOp::eKeep,
                    .compareOp = vkhpp::CompareOp::eAlways,
                    .compareMask = 0,
                    .writeMask = 0,
                    .reference = 0,
                },
            .minDepthBounds = 0.0f,
            .maxDepthBounds = 0.0f,
        };
        const std::vector<vkhpp::PipelineColorBlendAttachmentState> pipelineColorBlendAttachments =
            {
                vkhpp::PipelineColorBlendAttachmentState{
                    .blendEnable = VK_FALSE,
                    .srcColorBlendFactor = vkhpp::BlendFactor::eOne,
                    .dstColorBlendFactor = vkhpp::BlendFactor::eOneMinusSrcAlpha,
                    .colorBlendOp = vkhpp::BlendOp::eAdd,
                    .srcAlphaBlendFactor = vkhpp::BlendFactor::eOne,
                    .dstAlphaBlendFactor = vkhpp::BlendFactor::eOneMinusSrcAlpha,
                    .alphaBlendOp = vkhpp::BlendOp::eAdd,
                    .colorWriteMask =
                        vkhpp::ColorComponentFlagBits::eR | vkhpp::ColorComponentFlagBits::eG |
                        vkhpp::ColorComponentFlagBits::eB | vkhpp::ColorComponentFlagBits::eA,
                },
            };
        const vkhpp::PipelineColorBlendStateCreateInfo pipelineColorBlendStateCreateInfo = {
            .logicOpEnable = VK_FALSE,
            .logicOp = vkhpp::LogicOp::eCopy,
            .attachmentCount = static_cast<uint32_t>(pipelineColorBlendAttachments.size()),
            .pAttachments = pipelineColorBlendAttachments.data(),
            .blendConstants = {{
                0.0f,
                0.0f,
                0.0f,
                0.0f,
            }},
        };
        const std::vector<vkhpp::DynamicState> pipelineDynamicStates = {
            vkhpp::DynamicState::eViewport,
            vkhpp::DynamicState::eScissor,
        };
        const vkhpp::PipelineDynamicStateCreateInfo pipelineDynamicStateCreateInfo = {
            .dynamicStateCount = static_cast<uint32_t>(pipelineDynamicStates.size()),
            .pDynamicStates = pipelineDynamicStates.data(),
        };
        const vkhpp::GraphicsPipelineCreateInfo pipelineCreateInfo = {
            .stageCount = static_cast<uint32_t>(pipelineStages.size()),
            .pStages = pipelineStages.data(),
            .pVertexInputState = &pipelineVertexInputStateCreateInfo,
            .pInputAssemblyState = &pipelineInputAssemblyStateCreateInfo,
            .pTessellationState = nullptr,
            .pViewportState = &pipelineViewportStateCreateInfo,
            .pRasterizationState = &pipelineRasterStateCreateInfo,
            .pMultisampleState = &pipelineMultisampleStateCreateInfo,
            .pDepthStencilState = &pipelineDepthStencilStateCreateInfo,
            .pColorBlendState = &pipelineColorBlendStateCreateInfo,
            .pDynamicState = &pipelineDynamicStateCreateInfo,
            .layout = *pipelineLayout,
            .renderPass = *params.framebuffer->renderpass,
            .subpass = 0,
            .basePipelineHandle = VK_NULL_HANDLE,
            .basePipelineIndex = 0,
        };
        auto pipeline = GFXSTREAM_EXPECT_VKHPP_RV(
            vk.device->createGraphicsPipelineUnique({}, pipelineCreateInfo));

        return PipelineBundle{
            .vert = std::move(vertShaderModule),
            .frag = std::move(fragShaderModule),
            .pipelineLayout = std::move(pipelineLayout),
            .pipeline = std::move(pipeline),
        };
    }

    Result<Image> DownloadImage(TypicalVkTestEnvironment& vk, uint32_t width, uint32_t height,
                                const vkhpp::UniqueImage& image, vkhpp::ImageLayout currentLayout,
                                vkhpp::ImageLayout returnedLayout) {
        static constexpr const VkDeviceSize kStagingBufferSize = 32 * 1024 * 1024;
        auto stagingBuffer = GFXSTREAM_EXPECT(CreateBuffer(
            vk, kStagingBufferSize,
            vkhpp::BufferUsageFlagBits::eTransferDst | vkhpp::BufferUsageFlagBits::eTransferSrc,
            vkhpp::MemoryPropertyFlagBits::eHostVisible |
                vkhpp::MemoryPropertyFlagBits::eHostCoherent));

        GFXSTREAM_EXPECT(DoCommandsImmediate(vk, [&](vkhpp::UniqueCommandBuffer& cmd) {
            if (currentLayout != vkhpp::ImageLayout::eTransferSrcOptimal) {
                const std::vector<vkhpp::ImageMemoryBarrier> imageMemoryBarriers = {
                    vkhpp::ImageMemoryBarrier{
                        .srcAccessMask = vkhpp::AccessFlagBits::eMemoryRead |
                                         vkhpp::AccessFlagBits::eMemoryWrite,
                        .dstAccessMask = vkhpp::AccessFlagBits::eTransferRead,
                        .oldLayout = currentLayout,
                        .newLayout = vkhpp::ImageLayout::eTransferSrcOptimal,
                        .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
                        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
                        .image = *image,
                        .subresourceRange =
                            {
                                .aspectMask = vkhpp::ImageAspectFlagBits::eColor,
                                .baseMipLevel = 0,
                                .levelCount = 1,
                                .baseArrayLayer = 0,
                                .layerCount = 1,
                            },
                    },
                };
                cmd->pipelineBarrier(
                    /*srcStageMask=*/vkhpp::PipelineStageFlagBits::eAllCommands,
                    /*dstStageMask=*/vkhpp::PipelineStageFlagBits::eAllCommands,
                    /*dependencyFlags=*/{},
                    /*memoryBarriers=*/{},
                    /*bufferMemoryBarriers=*/{},
                    /*imageMemoryBarriers=*/imageMemoryBarriers);
            }

            const std::vector<vkhpp::BufferImageCopy> regions = {
                vkhpp::BufferImageCopy{
                    .bufferOffset = 0,
                    .bufferRowLength = 0,
                    .bufferImageHeight = 0,
                    .imageSubresource =
                        {
                            .aspectMask = vkhpp::ImageAspectFlagBits::eColor,
                            .mipLevel = 0,
                            .baseArrayLayer = 0,
                            .layerCount = 1,
                        },
                    .imageOffset =
                        {
                            .x = 0,
                            .y = 0,
                            .z = 0,
                        },
                    .imageExtent =
                        {
                            .width = width,
                            .height = height,
                            .depth = 1,
                        },
                },
            };
            cmd->copyImageToBuffer(*image, vkhpp::ImageLayout::eTransferSrcOptimal,
                                   *stagingBuffer.buffer, regions);

            if (returnedLayout != vkhpp::ImageLayout::eTransferSrcOptimal) {
                const std::vector<vkhpp::ImageMemoryBarrier> imageMemoryBarriers = {
                    vkhpp::ImageMemoryBarrier{
                        .srcAccessMask = vkhpp::AccessFlagBits::eTransferRead,
                        .dstAccessMask = vkhpp::AccessFlagBits::eMemoryRead |
                                         vkhpp::AccessFlagBits::eMemoryWrite,
                        .oldLayout = vkhpp::ImageLayout::eTransferSrcOptimal,
                        .newLayout = returnedLayout,
                        .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
                        .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
                        .image = *image,
                        .subresourceRange =
                            {
                                .aspectMask = vkhpp::ImageAspectFlagBits::eColor,
                                .baseMipLevel = 0,
                                .levelCount = 1,
                                .baseArrayLayer = 0,
                                .layerCount = 1,
                            },
                    },
                };
                cmd->pipelineBarrier(
                    /*srcStageMask=*/vkhpp::PipelineStageFlagBits::eAllCommands,
                    /*dstStageMask=*/vkhpp::PipelineStageFlagBits::eAllCommands,
                    /*dependencyFlags=*/{},
                    /*memoryBarriers=*/{},
                    /*bufferMemoryBarriers=*/{},
                    /*imageMemoryBarriers=*/imageMemoryBarriers);
            }
            return Ok{};
        }));

        std::vector<uint32_t> outPixels;
        outPixels.resize(width * height);

        auto* mapped = GFXSTREAM_EXPECT_VKHPP_RV(
            vk.device->mapMemory(*stagingBuffer.bufferMemory, 0, VK_WHOLE_SIZE));
        std::memcpy(outPixels.data(), mapped, sizeof(uint32_t) * outPixels.size());
        vk.device->unmapMemory(*stagingBuffer.bufferMemory);

        return Image{
            .width = width,
            .height = height,
            .pixels = outPixels,
        };
    }

    void DoFillAndRenderFromAhb(uint32_t ahbFormat) {
        const uint32_t width = 1920;
        const uint32_t height = 1080;
        const auto goldenPixel = PixelR8G8B8A8(0, 255, 255, 255);

        auto ahb =
            GFXSTREAM_ASSERT(ScopedAHardwareBuffer::Allocate(*mGralloc, width, height, ahbFormat));

        GFXSTREAM_ASSERT(FillAhb(ahb, goldenPixel));

        const vkhpp::PhysicalDeviceVulkan11Features deviceFeatures = {
            .samplerYcbcrConversion = VK_TRUE,
        };
        auto vk = GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment({
            .deviceExtensions = {{VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME}},
            .deviceCreateInfoPNext = &deviceFeatures,
        }));

        auto ahbImage =
            GFXSTREAM_ASSERT(CreateImageWithAhb(vk, ahb, vkhpp::ImageUsageFlagBits::eSampled,
                                                vkhpp::ImageLayout::eShaderReadOnlyOptimal));

        auto framebuffer = GFXSTREAM_ASSERT(CreateFramebuffer(
            vk, width, height, /*colorAttachmentFormat=*/vkhpp::Format::eR8G8B8A8Unorm));

        const vkhpp::Sampler ahbSamplerHandle = *ahbImage.imageSampler;
        auto descriptorSet0 = GFXSTREAM_ASSERT(
            CreateDescriptorSet(vk,
                                /*bindings=*/
                                {{
                                    .binding = 0,
                                    .descriptorType = vkhpp::DescriptorType::eCombinedImageSampler,
                                    .descriptorCount = 1,
                                    .stageFlags = vkhpp::ShaderStageFlagBits::eFragment,
                                    .pImmutableSamplers = &ahbSamplerHandle,
                                }},
                                /*writes=*/
                                {{
                                    .binding = 0,
                                    .image = {{
                                        .imageView = *ahbImage.imageView,
                                        .imageLayout = vkhpp::ImageLayout::eShaderReadOnlyOptimal,
                                        .imageSampler = *ahbImage.imageSampler,
                                    }},
                                }}));

        auto pipeline =
            GFXSTREAM_ASSERT(CreatePipeline(vk, {
                                                    .vert = kFullscreenTriangleWithUVVert,
                                                    .frag = kBlitSampler2dFrag,
                                                    .descriptorSets = {&descriptorSet0},
                                                    .framebuffer = &framebuffer,
                                                }));

        GFXSTREAM_ASSERT(DoCommandsImmediate(vk, [&](vkhpp::UniqueCommandBuffer& cmd) {
            const std::vector<vkhpp::ClearValue> renderPassBeginClearValues = {
                vkhpp::ClearValue{
                    .color =
                        {
                            .float32 = {{
                                1.0f,
                                0.0f,
                                0.0f,
                                1.0f,
                            }},
                        },
                },
            };
            const vkhpp::RenderPassBeginInfo renderPassBeginInfo = {
                .renderPass = *framebuffer.renderpass,
                .framebuffer = *framebuffer.framebuffer,
                .renderArea =
                    {
                        .offset =
                            {
                                .x = 0,
                                .y = 0,
                            },
                        .extent =
                            {
                                .width = width,
                                .height = height,
                            },
                    },
                .clearValueCount = static_cast<uint32_t>(renderPassBeginClearValues.size()),
                .pClearValues = renderPassBeginClearValues.data(),
            };
            cmd->beginRenderPass(renderPassBeginInfo, vkhpp::SubpassContents::eInline);
            cmd->bindPipeline(vkhpp::PipelineBindPoint::eGraphics, *pipeline.pipeline);
            cmd->bindDescriptorSets(vkhpp::PipelineBindPoint::eGraphics, *pipeline.pipelineLayout,
                                    /*firstSet=*/0, {*descriptorSet0.ds},
                                    /*dynamicOffsets=*/{});
            const vkhpp::Viewport viewport = {
                .x = 0.0f,
                .y = 0.0f,
                .width = static_cast<float>(width),
                .height = static_cast<float>(height),
                .minDepth = 0.0f,
                .maxDepth = 1.0f,
            };
            cmd->setViewport(0, {viewport});
            const vkhpp::Rect2D scissor = {
                .offset =
                    {
                        .x = 0,
                        .y = 0,
                    },
                .extent =
                    {
                        .width = width,
                        .height = height,
                    },
            };
            cmd->setScissor(0, {scissor});
            cmd->draw(3, 1, 0, 0);
            cmd->endRenderPass();
            return Ok{};
        }));

        const auto actualImage = GFXSTREAM_ASSERT(
            DownloadImage(vk, width, height, framebuffer.colorAttachment->image,
                          /*currentLayout=*/vkhpp::ImageLayout::eColorAttachmentOptimal,
                          /*returnedLayout=*/vkhpp::ImageLayout::eColorAttachmentOptimal));

        const auto expectedImage = ImageFromColor(width, height, goldenPixel);
        EXPECT_THAT(AreImagesSimilar(expectedImage, actualImage), IsTrue());
    }
};

TEST_P(GfxstreamEnd2EndVkTest, Basic) {
    auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());
}

TEST_P(GfxstreamEnd2EndVkTest, ImportAHB) {
    auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());

    const uint32_t width = 32;
    const uint32_t height = 32;
    auto ahb = GFXSTREAM_ASSERT(ScopedAHardwareBuffer::Allocate(
        *mGralloc, width, height, GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM));

    const VkNativeBufferANDROID imageNativeBufferInfo = {
        .sType = VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID,
        .handle = mGralloc->getNativeHandle(ahb),
    };

    auto vkQueueSignalReleaseImageANDROID = PFN_vkQueueSignalReleaseImageANDROID(
        device->getProcAddr("vkQueueSignalReleaseImageANDROID"));
    ASSERT_THAT(vkQueueSignalReleaseImageANDROID, NotNull());

    const vkhpp::ImageCreateInfo imageCreateInfo = {
        .pNext = &imageNativeBufferInfo,
        .imageType = vkhpp::ImageType::e2D,
        .extent.width = width,
        .extent.height = height,
        .extent.depth = 1,
        .mipLevels = 1,
        .arrayLayers = 1,
        .format = vkhpp::Format::eR8G8B8A8Unorm,
        .tiling = vkhpp::ImageTiling::eOptimal,
        .initialLayout = vkhpp::ImageLayout::eUndefined,
        .usage = vkhpp::ImageUsageFlagBits::eSampled |
                 vkhpp::ImageUsageFlagBits::eTransferDst |
                 vkhpp::ImageUsageFlagBits::eTransferSrc,
        .sharingMode = vkhpp::SharingMode::eExclusive,
        .samples = vkhpp::SampleCountFlagBits::e1,
    };
    auto image = device->createImageUnique(imageCreateInfo).value;

    vkhpp::MemoryRequirements imageMemoryRequirements{};
    device->getImageMemoryRequirements(*image, &imageMemoryRequirements);

    const uint32_t imageMemoryIndex = utils::getMemoryType(
        physicalDevice, imageMemoryRequirements, vkhpp::MemoryPropertyFlagBits::eDeviceLocal);
    ASSERT_THAT(imageMemoryIndex, Not(Eq(-1)));

    const vkhpp::MemoryAllocateInfo imageMemoryAllocateInfo = {
        .allocationSize = imageMemoryRequirements.size,
        .memoryTypeIndex = imageMemoryIndex,
    };

    auto imageMemory = device->allocateMemoryUnique(imageMemoryAllocateInfo).value;
    ASSERT_THAT(imageMemory, IsValidHandle());
    ASSERT_THAT(device->bindImageMemory(*image, *imageMemory, 0), IsVkSuccess());

    const vkhpp::BufferCreateInfo bufferCreateInfo = {
        .size = static_cast<VkDeviceSize>(12 * 1024 * 1024),
        .usage = vkhpp::BufferUsageFlagBits::eTransferDst |
                 vkhpp::BufferUsageFlagBits::eTransferSrc,
        .sharingMode = vkhpp::SharingMode::eExclusive,
    };
    auto stagingBuffer = device->createBufferUnique(bufferCreateInfo).value;
    ASSERT_THAT(stagingBuffer, IsValidHandle());

    vkhpp::MemoryRequirements stagingBufferMemoryRequirements{};
    device->getBufferMemoryRequirements(*stagingBuffer, &stagingBufferMemoryRequirements);

    const auto stagingBufferMemoryType = utils::getMemoryType(
        physicalDevice, stagingBufferMemoryRequirements,
        vkhpp::MemoryPropertyFlagBits::eHostVisible | vkhpp::MemoryPropertyFlagBits::eHostCoherent);

    const vkhpp::MemoryAllocateInfo stagingBufferMemoryAllocateInfo = {
        .allocationSize = stagingBufferMemoryRequirements.size,
        .memoryTypeIndex = stagingBufferMemoryType,
    };
    auto stagingBufferMemory = device->allocateMemoryUnique(stagingBufferMemoryAllocateInfo).value;
    ASSERT_THAT(stagingBufferMemory, IsValidHandle());
    ASSERT_THAT(device->bindBufferMemory(*stagingBuffer, *stagingBufferMemory, 0), IsVkSuccess());

    const vkhpp::CommandPoolCreateInfo commandPoolCreateInfo = {
        .queueFamilyIndex = queueFamilyIndex,
    };

    auto commandPool = device->createCommandPoolUnique(commandPoolCreateInfo).value;
    ASSERT_THAT(stagingBufferMemory, IsValidHandle());

    const vkhpp::CommandBufferAllocateInfo commandBufferAllocateInfo = {
        .level = vkhpp::CommandBufferLevel::ePrimary,
        .commandPool = *commandPool,
        .commandBufferCount = 1,
    };
    auto commandBuffers = device->allocateCommandBuffersUnique(commandBufferAllocateInfo).value;
    ASSERT_THAT(commandBuffers, Not(IsEmpty()));
    auto commandBuffer = std::move(commandBuffers[0]);
    ASSERT_THAT(commandBuffer, IsValidHandle());

    const vkhpp::CommandBufferBeginInfo commandBufferBeginInfo = {
        .flags = vkhpp::CommandBufferUsageFlagBits::eOneTimeSubmit,
    };
    commandBuffer->begin(commandBufferBeginInfo);
    commandBuffer->end();

    std::vector<vkhpp::CommandBuffer> commandBufferHandles;
    commandBufferHandles.push_back(*commandBuffer);

    auto transferFence = device->createFenceUnique(vkhpp::FenceCreateInfo()).value;
    ASSERT_THAT(commandBuffer, IsValidHandle());

    const vkhpp::SubmitInfo submitInfo = {
        .commandBufferCount = static_cast<uint32_t>(commandBufferHandles.size()),
        .pCommandBuffers = commandBufferHandles.data(),
    };
    queue.submit(submitInfo, *transferFence);

    auto waitResult = device->waitForFences(*transferFence, VK_TRUE, AsVkTimeout(3s));
    ASSERT_THAT(waitResult, IsVkSuccess());

    int fence;

    auto result = vkQueueSignalReleaseImageANDROID(queue, 0, nullptr, *image, &fence);
    ASSERT_THAT(result, Eq(VK_SUCCESS));
    ASSERT_THAT(fence, Not(Eq(-1)));

    ASSERT_THAT(mSync->wait(fence, 3000), Eq(0));
}

TEST_P(GfxstreamEnd2EndVkTest, DeferredImportAHB) {
    auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());

    const uint32_t width = 32;
    const uint32_t height = 32;
    auto ahb = GFXSTREAM_ASSERT(ScopedAHardwareBuffer::Allocate(
        *mGralloc, width, height, GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM));

    auto vkQueueSignalReleaseImageANDROID = PFN_vkQueueSignalReleaseImageANDROID(
        device->getProcAddr("vkQueueSignalReleaseImageANDROID"));
    ASSERT_THAT(vkQueueSignalReleaseImageANDROID, NotNull());

    const vkhpp::ImageCreateInfo imageCreateInfo = {
        .pNext = nullptr,
        .imageType = vkhpp::ImageType::e2D,
        .extent.width = width,
        .extent.height = height,
        .extent.depth = 1,
        .mipLevels = 1,
        .arrayLayers = 1,
        .format = vkhpp::Format::eR8G8B8A8Unorm,
        .tiling = vkhpp::ImageTiling::eOptimal,
        .initialLayout = vkhpp::ImageLayout::eUndefined,
        .usage = vkhpp::ImageUsageFlagBits::eSampled |
                 vkhpp::ImageUsageFlagBits::eTransferDst |
                 vkhpp::ImageUsageFlagBits::eTransferSrc,
        .sharingMode = vkhpp::SharingMode::eExclusive,
        .samples = vkhpp::SampleCountFlagBits::e1,
    };
    auto image = device->createImageUnique(imageCreateInfo).value;

    // NOTE: Binding the VkImage to the AHB happens after the VkImage is created.
    const VkNativeBufferANDROID imageNativeBufferInfo = {
        .sType = VK_STRUCTURE_TYPE_NATIVE_BUFFER_ANDROID,
        .handle = mGralloc->getNativeHandle(ahb),
    };

    const vkhpp::BindImageMemoryInfo imageBindMemoryInfo = {
        .pNext = &imageNativeBufferInfo,
        .image = *image,
        .memory = VK_NULL_HANDLE,
        .memoryOffset = 0,
    };
    ASSERT_THAT(device->bindImageMemory2({imageBindMemoryInfo}), IsVkSuccess());

    std::vector<vkhpp::Semaphore> semaphores;
    int fence;

    auto result = vkQueueSignalReleaseImageANDROID(queue, 0, nullptr, *image, &fence);
    ASSERT_THAT(result, Eq(VK_SUCCESS));
    ASSERT_THAT(fence, Not(Eq(-1)));

    ASSERT_THAT(mSync->wait(fence, 3000), Eq(0));
}

TEST_P(GfxstreamEnd2EndVkTest, BlobAHBIsNotMapable) {
    if (GetParam().with_gl) {
        GTEST_SKIP()
            << "Skipping test, data buffers are currently only supported in Vulkan only mode.";
    }
    if (GetParam().with_features.count("VulkanUseDedicatedAhbMemoryType") == 0) {
        GTEST_SKIP()
            << "Skipping test, AHB test only makes sense with VulkanUseDedicatedAhbMemoryType.";
    }

    auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());

    const uint32_t width = 32;
    const uint32_t height = 1;
    auto ahb = GFXSTREAM_ASSERT(
        ScopedAHardwareBuffer::Allocate(*mGralloc, width, height, GFXSTREAM_AHB_FORMAT_BLOB));

    const vkhpp::ExternalMemoryBufferCreateInfo externalMemoryBufferCreateInfo = {
        .handleTypes = vkhpp::ExternalMemoryHandleTypeFlagBits::eAndroidHardwareBufferANDROID,
    };
    const vkhpp::BufferCreateInfo bufferCreateInfo = {
        .pNext = &externalMemoryBufferCreateInfo,
        .size = width,
        .usage = vkhpp::BufferUsageFlagBits::eTransferDst |
                 vkhpp::BufferUsageFlagBits::eTransferSrc |
                 vkhpp::BufferUsageFlagBits::eVertexBuffer,
        .sharingMode = vkhpp::SharingMode::eExclusive,
    };
    auto buffer = device->createBufferUnique(bufferCreateInfo).value;
    ASSERT_THAT(buffer, IsValidHandle());

    auto vkGetAndroidHardwareBufferPropertiesANDROID =
        reinterpret_cast<PFN_vkGetAndroidHardwareBufferPropertiesANDROID>(
            device->getProcAddr("vkGetAndroidHardwareBufferPropertiesANDROID"));
    ASSERT_THAT(vkGetAndroidHardwareBufferPropertiesANDROID, NotNull());

    VkAndroidHardwareBufferPropertiesANDROID bufferProperties = {
        .sType = VK_STRUCTURE_TYPE_ANDROID_HARDWARE_BUFFER_PROPERTIES_ANDROID,
        .pNext = nullptr,
    };
    ASSERT_THAT(vkGetAndroidHardwareBufferPropertiesANDROID(*device, ahb, &bufferProperties),
                Eq(VK_SUCCESS));

    const vkhpp::MemoryRequirements bufferMemoryRequirements{
        .size = bufferProperties.allocationSize,
        .alignment = 0,
        .memoryTypeBits = bufferProperties.memoryTypeBits,
    };

    const auto memoryProperties = physicalDevice.getMemoryProperties();
    for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; i++) {
        if (!(bufferMemoryRequirements.memoryTypeBits & (1 << i))) {
            continue;
        }

        const auto memoryPropertyFlags = memoryProperties.memoryTypes[i].propertyFlags;
        EXPECT_THAT(memoryPropertyFlags & vkhpp::MemoryPropertyFlagBits::eHostVisible,
                    Ne(vkhpp::MemoryPropertyFlagBits::eHostVisible));
    }

    const auto bufferMemoryType = utils::getMemoryType(physicalDevice, bufferMemoryRequirements,
                                                       vkhpp::MemoryPropertyFlagBits::eDeviceLocal);
    ASSERT_THAT(bufferMemoryType, Ne(-1));

    const vkhpp::ImportAndroidHardwareBufferInfoANDROID importHardwareBufferInfo = {
        .buffer = ahb,
    };
    const vkhpp::MemoryAllocateInfo bufferMemoryAllocateInfo = {
        .pNext = &importHardwareBufferInfo,
        .allocationSize = bufferMemoryRequirements.size,
        .memoryTypeIndex = bufferMemoryType,
    };
    auto bufferMemory = device->allocateMemoryUnique(bufferMemoryAllocateInfo).value;
    ASSERT_THAT(bufferMemory, IsValidHandle());

    ASSERT_THAT(device->bindBufferMemory(*buffer, *bufferMemory, 0), IsVkSuccess());
}

TEST_P(GfxstreamEnd2EndVkTest, HostMemory) {
    static constexpr const vkhpp::DeviceSize kSize = 16 * 1024;

    auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());

    uint32_t hostMemoryTypeIndex = -1;
    const auto memoryProperties = physicalDevice.getMemoryProperties();
    for (uint32_t i = 0; i < memoryProperties.memoryTypeCount; i++) {
        const vkhpp::MemoryType& memoryType = memoryProperties.memoryTypes[i];
        if (memoryType.propertyFlags & vkhpp::MemoryPropertyFlagBits::eHostVisible) {
            hostMemoryTypeIndex = i;
        }
    }
    if (hostMemoryTypeIndex == -1) {
        GTEST_SKIP() << "Skipping test due to no host visible memory type.";
        return;
    }

    const vkhpp::MemoryAllocateInfo memoryAllocateInfo = {
        .allocationSize = kSize,
        .memoryTypeIndex = hostMemoryTypeIndex,
    };
    auto memory = device->allocateMemoryUnique(memoryAllocateInfo).value;
    ASSERT_THAT(memory, IsValidHandle());

    void* mapped = nullptr;

    auto mapResult = device->mapMemory(*memory, 0, VK_WHOLE_SIZE, vkhpp::MemoryMapFlags{}, &mapped);
    ASSERT_THAT(mapResult, IsVkSuccess());
    ASSERT_THAT(mapped, NotNull());

    auto* bytes = reinterpret_cast<uint8_t*>(mapped);
    std::memset(bytes, 0xFF, kSize);

    const vkhpp::MappedMemoryRange range = {
        .memory = *memory,
        .offset = 0,
        .size = kSize,
    };
    device->flushMappedMemoryRanges({range});
    device->invalidateMappedMemoryRanges({range});

    for (uint32_t i = 0; i < kSize; ++i) {
        EXPECT_THAT(bytes[i], Eq(0xFF));
    }
}

TEST_P(GfxstreamEnd2EndVkTest, GetPhysicalDeviceProperties2) {
    auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());

    auto props1 = physicalDevice.getProperties();
    auto props2 = physicalDevice.getProperties2();

    EXPECT_THAT(props1.vendorID, Eq(props2.properties.vendorID));
    EXPECT_THAT(props1.deviceID, Eq(props2.properties.deviceID));
}

TEST_P(GfxstreamEnd2EndVkTest, GetPhysicalDeviceFeatures2KHR) {
    auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());

    auto features1 = physicalDevice.getFeatures();
    auto features2 = physicalDevice.getFeatures2();
    EXPECT_THAT(features1.robustBufferAccess, Eq(features2.features.robustBufferAccess));
}

TEST_P(GfxstreamEnd2EndVkTest, GetPhysicalDeviceImageFormatProperties2KHR) {
    auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());

    const vkhpp::PhysicalDeviceImageFormatInfo2 imageFormatInfo = {
        .format = vkhpp::Format::eR8G8B8A8Unorm,
        .type = vkhpp::ImageType::e2D,
        .tiling = vkhpp::ImageTiling::eOptimal,
        .usage = vkhpp::ImageUsageFlagBits::eSampled,
    };
    const auto properties =
        GFXSTREAM_ASSERT_VKHPP_RV(physicalDevice.getImageFormatProperties2(imageFormatInfo));
    EXPECT_THAT(properties.imageFormatProperties.maxExtent.width, Ge(1));
    EXPECT_THAT(properties.imageFormatProperties.maxExtent.height, Ge(1));
    EXPECT_THAT(properties.imageFormatProperties.maxExtent.depth, Ge(1));
}

template <typename VkhppUniqueHandleType,
          typename VkhppHandleType = typename VkhppUniqueHandleType::element_type>
std::vector<VkhppHandleType> AsHandles(const std::vector<VkhppUniqueHandleType>& elements) {
    std::vector<VkhppHandleType> ret;
    ret.reserve(elements.size());
    for (const auto& e : elements) {
        ret.push_back(*e);
    }
    return ret;
}

struct DescriptorBundle {
    vkhpp::UniqueDescriptorPool descriptorPool;
    vkhpp::UniqueDescriptorSetLayout descriptorSetLayout;
    std::vector<vkhpp::UniqueDescriptorSet> descriptorSets;
};

Result<Ok> ReallocateDescriptorBundleSets(vkhpp::Device device, uint32_t count,
                                          DescriptorBundle* bundle) {
    if (!bundle->descriptorSetLayout) {
        return gfxstream::unexpected("Invalid descriptor set layout");
    }

    const std::vector<vkhpp::DescriptorSetLayout> descriptorSetLayouts(count, *bundle->descriptorSetLayout);
    const vkhpp::DescriptorSetAllocateInfo descriptorSetAllocateInfo = {
        .descriptorPool = *bundle->descriptorPool,
        .descriptorSetCount = count,
        .pSetLayouts = descriptorSetLayouts.data(),
    };
    auto descriptorSets =
        GFXSTREAM_EXPECT_VKHPP_RV(device.allocateDescriptorSetsUnique(descriptorSetAllocateInfo));
    bundle->descriptorSets = std::move(descriptorSets);
    return Ok{};
}

Result<DescriptorBundle> AllocateDescriptorBundle(vkhpp::Device device, uint32_t count) {
    const vkhpp::DescriptorPoolSize descriptorPoolSize = {
        .type = vkhpp::DescriptorType::eUniformBuffer,
        .descriptorCount = 1 * count,
    };
    const vkhpp::DescriptorPoolCreateInfo descriptorPoolCreateInfo = {
        .flags = vkhpp::DescriptorPoolCreateFlagBits::eFreeDescriptorSet,
        .maxSets = count,
        .poolSizeCount = 1,
        .pPoolSizes = &descriptorPoolSize,
    };
    auto descriptorPool =
        GFXSTREAM_EXPECT_VKHPP_RV(device.createDescriptorPoolUnique(descriptorPoolCreateInfo));

    const vkhpp::DescriptorSetLayoutBinding descriptorSetBinding = {
        .binding = 0,
        .descriptorType = vkhpp::DescriptorType::eUniformBuffer,
        .descriptorCount = 1,
        .stageFlags = vkhpp::ShaderStageFlagBits::eVertex,
    };
    const vkhpp::DescriptorSetLayoutCreateInfo descriptorSetLayoutInfo = {
        .bindingCount = 1,
        .pBindings = &descriptorSetBinding,
    };
    auto descriptorSetLayout =
        GFXSTREAM_EXPECT_VKHPP_RV(device.createDescriptorSetLayoutUnique(descriptorSetLayoutInfo));

    DescriptorBundle bundle = {
        .descriptorPool = std::move(descriptorPool),
        .descriptorSetLayout = std::move(descriptorSetLayout),
    };
    GFXSTREAM_EXPECT(ReallocateDescriptorBundleSets(device, count, &bundle));
    return std::move(bundle);
}

// Tests creating a bunch of descriptor sets and freeing them via vkFreeDescriptorSet.
// 1. Via vkFreeDescriptorSet directly
// 2. Via vkResetDescriptorPool
// 3. Via vkDestroyDescriptorPool
// 4. Via vkResetDescriptorPool and double frees in vkFreeDescriptorSet
// 5. Via vkResetDescriptorPool and double frees in vkFreeDescriptorSet
// 4. Via vkResetDescriptorPool, creating more, and freeing vai vkFreeDescriptorSet
// (because vkFree* APIs are expected to never fail)
// https://github.com/KhronosGroup/Vulkan-Docs/issues/1070
TEST_P(GfxstreamEnd2EndVkTest, DescriptorSetAllocFree) {
    constexpr const uint32_t kNumSets = 4;

    auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());

    auto bundle = GFXSTREAM_ASSERT(AllocateDescriptorBundle(*device, kNumSets));

    auto descriptorSetHandles = AsHandles(bundle.descriptorSets);
    EXPECT_THAT(device->freeDescriptorSets(*bundle.descriptorPool, kNumSets, descriptorSetHandles.data()), IsVkSuccess());

    // The double free should also work
    EXPECT_THAT(device->freeDescriptorSets(*bundle.descriptorPool, kNumSets, descriptorSetHandles.data()), IsVkSuccess());

    // Alloc/free again should also work
    GFXSTREAM_ASSERT(ReallocateDescriptorBundleSets(*device, kNumSets, &bundle));

    descriptorSetHandles = AsHandles(bundle.descriptorSets);
    EXPECT_THAT(device->freeDescriptorSets(*bundle.descriptorPool, kNumSets, descriptorSetHandles.data()), IsVkSuccess());
}

TEST_P(GfxstreamEnd2EndVkTest, DescriptorSetAllocFreeReset) {
    constexpr const uint32_t kNumSets = 4;

    auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());

    auto bundle = GFXSTREAM_ASSERT(AllocateDescriptorBundle(*device, kNumSets));

    device->resetDescriptorPool(*bundle.descriptorPool);

    // The double free should also work
    auto descriptorSetHandles = AsHandles(bundle.descriptorSets);
    EXPECT_THAT(device->freeDescriptorSets(*bundle.descriptorPool, kNumSets, descriptorSetHandles.data()), IsVkSuccess());

    // Alloc/reset/free again should also work
    GFXSTREAM_ASSERT(ReallocateDescriptorBundleSets(*device, kNumSets, &bundle));

    device->resetDescriptorPool(*bundle.descriptorPool);

    descriptorSetHandles = AsHandles(bundle.descriptorSets);
    EXPECT_THAT(device->freeDescriptorSets(*bundle.descriptorPool, kNumSets, descriptorSetHandles.data()), IsVkSuccess());
}

TEST_P(GfxstreamEnd2EndVkTest, DISABLED_DescriptorSetAllocFreeDestroy) {
    constexpr const uint32_t kNumSets = 4;

    auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());

    auto bundle = GFXSTREAM_ASSERT(AllocateDescriptorBundle(*device, kNumSets));

    device->destroyDescriptorPool(*bundle.descriptorPool);

    // The double free should also work
    auto descriptorSetHandles = AsHandles(bundle.descriptorSets);
    EXPECT_THAT(device->freeDescriptorSets(*bundle.descriptorPool, kNumSets, descriptorSetHandles.data()), IsVkSuccess());
}

TEST_P(GfxstreamEnd2EndVkTest, MultiThreadedShutdown) {
    constexpr const int kNumIterations = 20;
    for (int i = 0; i < kNumIterations; i++) {
        auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
            GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());

        const vkhpp::BufferCreateInfo bufferCreateInfo = {
            .size = 1024,
            .usage = vkhpp::BufferUsageFlagBits::eTransferSrc,
        };

        // TODO: switch to std::barrier with arrive_and_wait().
        std::atomic_int threadsReady{0};
        std::vector<std::thread> threads;

        constexpr const int kNumThreads = 5;
        for (int t = 0; t < kNumThreads; t++) {
            threads.emplace_back([&, this](){
                // Perform some work to ensure host RenderThread started.
                auto buffer1 = device->createBufferUnique(bufferCreateInfo).value;

                ++threadsReady;
                while (threadsReady.load() != kNumThreads) {}

                // Sleep a little which is hopefully enough time to potentially get
                // the corresponding host ASG RenderThreads to go sleep waiting for
                // a WAKEUP via a GFXSTREAM_CONTEXT_PING.
                std::this_thread::sleep_for(std::chrono::milliseconds(100));

                auto buffer2 = device->createBufferUnique(bufferCreateInfo).value;

                // 2 vkDestroyBuffer() calls happen here with the destruction of `buffer1`
                // and `buffer2`. vkDestroy*() calls are async (return `void`) and the
                // guest thread continues execution without waiting for the command to
                // complete on the host.
                //
                // The guest ASG and corresponding virtio gpu resource will also be
                // destructed here as a part of the thread_local HostConnection being
                // destructed.
                //
                // Note: Vulkan commands are given a sequence number in order to ensure that
                // commands from multi-threaded guest Vulkan apps are executed in order on the
                // host. Gfxstream's host Vulkan decoders will spin loop waiting for their turn to
                // process their next command.
                //
                // With all of the above, a deadlock would previouly occur with the following
                // sequence:
                //
                // T1: Host-RenderThread-1: <sleeping waiting for wakeup>
                //
                // T2: Host-RenderThread-2: <sleeping waiting for wakeup>
                //
                // T3: Guest-Thread-1: vkDestroyBuffer() called,
                //                     VkEncoder grabs sequence-number-10,
                //                     writes sequence-number-10 into ASG-1 via resource-1
                //
                // T4: Guest-Thread-2: vkDestroyBuffer() called,
                //                     VkEncoder grabs sequence-number-11,
                //                     writes into ASG-2 via resource-2
                //
                // T5: Guest-Thread-2: ASG-2 sends a VIRTIO_GPU_CMD_SUBMIT_3D with
                //                     GFXSTREAM_CONTEXT_PING on ASG-resource-2
                //
                // T6: Guest-Thread-2: guest thread finishes,
                //                     ASG-2 destructor destroys the virtio-gpu resource used,
                //                     destruction sends VIRTIO_GPU_CMD_RESOURCE_UNREF on
                //                     resource-2
                //
                // T7: Guest-Thread-1: ASG-1 sends VIRTIO_GPU_CMD_SUBMIT_3D with
                //                     GFXSTREAM_CONTEXT_PING on ASG-resource-1
                //
                // T8: Host-Virtio-Gpu-Thread: performs VIRTIO_GPU_CMD_SUBMIT_3D from T5,
                //                             pings ASG-2 which wakes up Host-RenderThread-2
                //
                // T9: Host-RenderThread-2: woken from T8,
                //                          reads sequence-number-11 from ASG-2,
                //                          spin looping waiting for sequence-number-10 to execute
                //
                // T10: Host-Virtio-Gpu-Thread: performs VIRTIO_GPU_CMD_RESOURCE_UNREF for
                //                              resource-2 from T6,
                //                              resource-2 is used by ASG-2 / Host-RenderThread-2
                //                              waits for Host-RenderThread-2 to finish
                //
                // DEADLOCKED HERE:
                //
                //   *  Host-Virtio-GpuThread is waiting for Host-RenderThread-2 to finish before
                //      it can finish destroying resource-2
                //
                //   *  Host-RenderThread-2 is waiting for Host-RenderThread-1 to execute
                //      sequence-number-10
                //
                //   *  Host-RenderThread-1 is asleep waiting for a GFXSTREAM_CONTEXT_PING
                //      from Host-Virtio-GpuThread
            });
        }

        for (auto& thread : threads) {
            thread.join();
        }
    }
}

TEST_P(GfxstreamEnd2EndVkTest, DeviceCreateWithDeviceGroup) {
    auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());

    const vkhpp::DeviceGroupDeviceCreateInfo deviceGroupDeviceCreateInfo = {
        .physicalDeviceCount = 1,
        .pPhysicalDevices = &physicalDevice,
    };

    const float queuePriority = 1.0f;
    const vkhpp::DeviceQueueCreateInfo deviceQueueCreateInfo = {
        .queueFamilyIndex = 0,
        .queueCount = 1,
        .pQueuePriorities = &queuePriority,
    };
    const vkhpp::DeviceCreateInfo deviceCreateInfo = {
        .pNext = &deviceGroupDeviceCreateInfo,
        .pQueueCreateInfos = &deviceQueueCreateInfo,
        .queueCreateInfoCount = 1,
    };
    auto device2 = GFXSTREAM_ASSERT_VKHPP_RV(physicalDevice.createDeviceUnique(deviceCreateInfo));
    ASSERT_THAT(device2, IsValidHandle());
}

TEST_P(GfxstreamEnd2EndVkTest, AcquireImageAndroidWithFence) {
    DoAcquireImageAndroidWithSync(/*withFence=*/true, /*withSemaphore=*/false);
}

TEST_P(GfxstreamEnd2EndVkTest, AcquireImageAndroidWithSemaphore) {
    DoAcquireImageAndroidWithSync(/*withFence=*/false, /*withSemaphore=*/true);
}

TEST_P(GfxstreamEnd2EndVkTest, AcquireImageAndroidWithFenceAndSemaphore) {
    DoAcquireImageAndroidWithSync(/*withFence=*/true, /*withSemaphore=*/true);
}

VKAPI_ATTR void VKAPI_CALL MemoryReportCallback(const VkDeviceMemoryReportCallbackDataEXT*, void*) {
    // Unused
}

TEST_P(GfxstreamEnd2EndVkTest, DeviceMemoryReport) {
    int userdata = 1;
    vkhpp::DeviceDeviceMemoryReportCreateInfoEXT deviceDeviceMemoryReportInfo = {
        .pfnUserCallback = &MemoryReportCallback,
        .pUserData = &userdata,
    };

    auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment({
            .deviceExtensions = {{
                VK_EXT_DEVICE_MEMORY_REPORT_EXTENSION_NAME,
            }},
            .deviceCreateInfoPNext = &deviceDeviceMemoryReportInfo,
        }));

    const vkhpp::MemoryAllocateInfo memoryAllocateInfo = {
        .allocationSize = 1024,
        .memoryTypeIndex = 0,
    };
    auto memory = device->allocateMemoryUnique(memoryAllocateInfo).value;
    ASSERT_THAT(memory, IsValidHandle());
}

TEST_P(GfxstreamEnd2EndVkTest, DescriptorUpdateTemplateWithWrapping) {
    auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());

    const vkhpp::BufferCreateInfo bufferCreateInfo = {
        .size = 1024,
        .usage = vkhpp::BufferUsageFlagBits::eUniformBuffer,
    };
    auto buffer = GFXSTREAM_ASSERT_VKHPP_RV(device->createBufferUnique(bufferCreateInfo));

    const std::vector<VkDescriptorBufferInfo> descriptorInfo = {
        VkDescriptorBufferInfo{
            .buffer = *buffer,
            .offset = 0,
            .range = 1024,
        },
        VkDescriptorBufferInfo{
            .buffer = *buffer,
            .offset = 0,
            .range = 1024,
        },
        VkDescriptorBufferInfo{
            .buffer = *buffer,
            .offset = 0,
            .range = 1024,
        },
        VkDescriptorBufferInfo{
            .buffer = *buffer,
            .offset = 0,
            .range = 1024,
        },
    };

    const std::vector<vkhpp::DescriptorPoolSize> descriptorPoolSizes = {
        {
            .type = vkhpp::DescriptorType::eUniformBuffer,
            .descriptorCount = 4,
        },
    };
    const vkhpp::DescriptorPoolCreateInfo descriptorPoolCreateInfo = {
        .flags = vkhpp::DescriptorPoolCreateFlagBits::eFreeDescriptorSet,
        .maxSets = 1,
        .poolSizeCount = static_cast<uint32_t>(descriptorPoolSizes.size()),
        .pPoolSizes = descriptorPoolSizes.data(),
    };
    auto descriptorPool =
        GFXSTREAM_ASSERT_VKHPP_RV(device->createDescriptorPoolUnique(descriptorPoolCreateInfo));

    const std::vector<vkhpp::DescriptorSetLayoutBinding> descriptorSetBindings = {
        {
            .binding = 0,
            .descriptorType = vkhpp::DescriptorType::eUniformBuffer,
            .descriptorCount = 1,
            .stageFlags = vkhpp::ShaderStageFlagBits::eVertex,
        },
        {
            .binding = 1,
            .descriptorType = vkhpp::DescriptorType::eUniformBuffer,
            .descriptorCount = 1,
            .stageFlags = vkhpp::ShaderStageFlagBits::eVertex,
        },
        {
            .binding = 2,
            .descriptorType = vkhpp::DescriptorType::eUniformBuffer,
            .descriptorCount = 1,
            .stageFlags = vkhpp::ShaderStageFlagBits::eVertex,
        },
        {
            .binding = 3,
            .descriptorType = vkhpp::DescriptorType::eUniformBuffer,
            .descriptorCount = 1,
            .stageFlags = vkhpp::ShaderStageFlagBits::eVertex,
        },
    };
    const vkhpp::DescriptorSetLayoutCreateInfo descriptorSetLayoutInfo = {
        .bindingCount = static_cast<uint32_t>(descriptorSetBindings.size()),
        .pBindings = descriptorSetBindings.data(),
    };
    auto descriptorSetLayout =
        GFXSTREAM_ASSERT_VKHPP_RV(device->createDescriptorSetLayoutUnique(descriptorSetLayoutInfo));

    const std::vector<vkhpp::DescriptorSetLayout> descriptorSetLayouts = {*descriptorSetLayout};
    const vkhpp::DescriptorSetAllocateInfo descriptorSetAllocateInfo = {
        .descriptorPool = *descriptorPool,
        .descriptorSetCount = static_cast<uint32_t>(descriptorSetLayouts.size()),
        .pSetLayouts = descriptorSetLayouts.data(),
    };
    auto descriptorSets =
        GFXSTREAM_ASSERT_VKHPP_RV(device->allocateDescriptorSetsUnique(descriptorSetAllocateInfo));
    auto descriptorSet = std::move(descriptorSets[0]);

    const vkhpp::PipelineLayoutCreateInfo pipelineLayoutCreateInfo = {
        .setLayoutCount = static_cast<uint32_t>(descriptorSetLayouts.size()),
        .pSetLayouts = descriptorSetLayouts.data(),
    };
    auto pipelineLayout =
        GFXSTREAM_ASSERT_VKHPP_RV(device->createPipelineLayoutUnique(pipelineLayoutCreateInfo));

    const std::vector<vkhpp::DescriptorUpdateTemplateEntry> descriptorUpdateEntries = {
        {
            .dstBinding = 0,
            .dstArrayElement = 0,
            .descriptorCount = 4,
            .descriptorType = vkhpp::DescriptorType::eUniformBuffer,
            .offset = 0,
            .stride = sizeof(VkDescriptorBufferInfo),
        },
    };
    const vkhpp::DescriptorUpdateTemplateCreateInfo descriptorUpdateTemplateCreateInfo = {
        .descriptorUpdateEntryCount = static_cast<uint32_t>(descriptorUpdateEntries.size()),
        .pDescriptorUpdateEntries = descriptorUpdateEntries.data(),
        .descriptorSetLayout = *descriptorSetLayout,
        .pipelineBindPoint = vkhpp::PipelineBindPoint::eGraphics,
        .pipelineLayout = *pipelineLayout,
        .set = 0,
    };
    auto descriptorUpdateTemplate = GFXSTREAM_ASSERT_VKHPP_RV(
        device->createDescriptorUpdateTemplateUnique(descriptorUpdateTemplateCreateInfo));

    device->updateDescriptorSetWithTemplate(*descriptorSet, *descriptorUpdateTemplate,
                                            descriptorInfo.data());
}

TEST_P(GfxstreamEnd2EndVkTest, MultiThreadedVkMapMemory) {
    auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());

    static constexpr const vkhpp::DeviceSize kSize = 1024;
    const vkhpp::BufferCreateInfo bufferCreateInfo = {
        .size = kSize,
        .usage = vkhpp::BufferUsageFlagBits::eTransferSrc,
    };
    auto buffer = device->createBufferUnique(bufferCreateInfo).value;

    vkhpp::MemoryRequirements bufferMemoryRequirements{};
    device->getBufferMemoryRequirements(*buffer, &bufferMemoryRequirements);

    const uint32_t bufferMemoryIndex = utils::getMemoryType(
        physicalDevice, bufferMemoryRequirements,
        vkhpp::MemoryPropertyFlagBits::eHostVisible | vkhpp::MemoryPropertyFlagBits::eHostCoherent);
    if (bufferMemoryIndex == -1) {
        GTEST_SKIP() << "Skipping test due to no memory type with HOST_VISIBLE | HOST_COHERENT.";
    }

    std::vector<std::thread> threads;
    std::atomic_int threadsReady{0};

    constexpr const int kNumThreads = 2;
    for (int t = 0; t < kNumThreads; t++) {
        threads.emplace_back([&, this]() {
            // Perform some work to ensure host RenderThread started.
            auto buffer2 = device->createBufferUnique(bufferCreateInfo).value;
            ASSERT_THAT(buffer2, IsValidHandle());

            ++threadsReady;
            while (threadsReady.load() != kNumThreads) {
            }

            constexpr const int kNumIterations = 100;
            for (int i = 0; i < kNumIterations; i++) {
                auto buffer3 = device->createBufferUnique(bufferCreateInfo).value;
                ASSERT_THAT(buffer3, IsValidHandle());

                const vkhpp::MemoryAllocateInfo buffer3MemoryAllocateInfo = {
                    .allocationSize = bufferMemoryRequirements.size,
                    .memoryTypeIndex = bufferMemoryIndex,
                };
                auto buffer3Memory = device->allocateMemoryUnique(buffer3MemoryAllocateInfo).value;
                ASSERT_THAT(buffer3Memory, IsValidHandle());

                ASSERT_THAT(device->bindBufferMemory(*buffer3, *buffer3Memory, 0), IsVkSuccess());

                void* mapped = nullptr;
                ASSERT_THAT(device->mapMemory(*buffer3Memory, 0, VK_WHOLE_SIZE,
                                              vkhpp::MemoryMapFlags{}, &mapped),
                            IsVkSuccess());
                ASSERT_THAT(mapped, NotNull());

                device->unmapMemory(*buffer3Memory);
            }
        });
    }

    for (auto& thread : threads) {
        thread.join();
    }
}

TEST_P(GfxstreamEnd2EndVkTest, MultiThreadedResetCommandBuffer) {
    auto [instance, physicalDevice, device, queue, queueFamilyIndex] =
        GFXSTREAM_ASSERT(SetUpTypicalVkTestEnvironment());

    static constexpr const vkhpp::DeviceSize kSize = 1024;
    const vkhpp::BufferCreateInfo bufferCreateInfo = {
        .size = kSize,
        .usage = vkhpp::BufferUsageFlagBits::eTransferSrc,
    };

    static std::mutex queue_mutex;
    std::vector<std::thread> threads;
    std::atomic_int threadsReady{0};

    constexpr const int kNumThreads = 10;
    for (int t = 0; t < kNumThreads; t++) {
        threads.emplace_back([&, this]() {
            // Perform some work to ensure host RenderThread started.
            auto buffer2 = device->createBufferUnique(bufferCreateInfo).value;
            ASSERT_THAT(buffer2, IsValidHandle());

            ++threadsReady;
            while (threadsReady.load() != kNumThreads) {
            }

            const vkhpp::CommandPoolCreateInfo commandPoolCreateInfo = {
                .queueFamilyIndex = queueFamilyIndex,
            };
            auto commandPool = device->createCommandPoolUnique(commandPoolCreateInfo).value;

            const vkhpp::CommandBufferAllocateInfo commandBufferAllocateInfo = {
                .level = vkhpp::CommandBufferLevel::ePrimary,
                .commandPool = *commandPool,
                .commandBufferCount = 1,
            };
            auto commandBuffers = device->allocateCommandBuffersUnique(commandBufferAllocateInfo).value;
            ASSERT_THAT(commandBuffers, Not(IsEmpty()));
            auto commandBuffer = std::move(commandBuffers[0]);
            ASSERT_THAT(commandBuffer, IsValidHandle());

            auto transferFence = device->createFenceUnique(vkhpp::FenceCreateInfo()).value;
            ASSERT_THAT(commandBuffer, IsValidHandle());

            constexpr const int kNumIterations = 1000;
            for (int i = 0; i < kNumIterations; i++) {
                commandBuffer->reset();
                const vkhpp::CommandBufferBeginInfo commandBufferBeginInfo = {
                    .flags = vkhpp::CommandBufferUsageFlagBits::eOneTimeSubmit,
                };
                commandBuffer->begin(commandBufferBeginInfo);

                commandBuffer->end();

                std::vector<vkhpp::CommandBuffer> commandBufferHandles;
                commandBufferHandles.push_back(*commandBuffer);

                const vkhpp::SubmitInfo submitInfo = {
                    .commandBufferCount = static_cast<uint32_t>(commandBufferHandles.size()),
                    .pCommandBuffers = commandBufferHandles.data(),
                };
                {
                    std::lock_guard<std::mutex> qm(queue_mutex);
                    queue.submit(submitInfo, *transferFence);
                }
                auto waitResult = device->waitForFences(*transferFence, VK_TRUE, AsVkTimeout(3s));
                ASSERT_THAT(waitResult, IsVkSuccess());
            }
        });
    }

    for (auto& thread : threads) {
        thread.join();
    }
}

TEST_P(GfxstreamEnd2EndVkTest, ImportAndBlitFromR8G8B8A8Ahb) {
    DoFillAndRenderFromAhb(GFXSTREAM_AHB_FORMAT_R8G8B8A8_UNORM);
}

TEST_P(GfxstreamEnd2EndVkTest, ImportAndBlitFromYCbCr888420Ahb) {
    DoFillAndRenderFromAhb(GFXSTREAM_AHB_FORMAT_Y8Cb8Cr8_420);
}

TEST_P(GfxstreamEnd2EndVkTest, ImportAndBlitFromYv12Ahb) {
    DoFillAndRenderFromAhb(GFXSTREAM_AHB_FORMAT_YV12);
}

std::vector<TestParams> GenerateTestCases() {
    std::vector<TestParams> cases = {TestParams{
                                         .with_gl = false,
                                         .with_vk = true,
                                         .with_transport = GfxstreamTransport::kVirtioGpuAsg,
                                     },
                                     TestParams{
                                         .with_gl = true,
                                         .with_vk = true,
                                         .with_transport = GfxstreamTransport::kVirtioGpuAsg,
                                     },
                                     TestParams{
                                         .with_gl = false,
                                         .with_vk = true,
                                         .with_transport = GfxstreamTransport::kVirtioGpuPipe,
                                     },
                                     TestParams{
                                         .with_gl = true,
                                         .with_vk = true,
                                         .with_transport = GfxstreamTransport::kVirtioGpuPipe,
                                     }};
    cases = WithAndWithoutFeatures(cases, {"VulkanSnapshots"});
    cases = WithAndWithoutFeatures(cases, {"VulkanUseDedicatedAhbMemoryType"});
    return cases;
}

INSTANTIATE_TEST_CASE_P(GfxstreamEnd2EndTests, GfxstreamEnd2EndVkTest,
                        ::testing::ValuesIn(GenerateTestCases()), &GetTestName);

}  // namespace
}  // namespace tests
}  // namespace gfxstream
