/*
 * Copyright (c) 2015-2026 The Khronos Group Inc.
 * Copyright (c) 2015-2026 Valve Corporation
 * Copyright (c) 2015-2026 LunarG, Inc.
 * Copyright (C) 2025 Arm Limited.
 *
 * 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 "binding.h"

#include <string.h>  // memset(), memcmp()
#include <cassert>
#include <algorithm>
#include <iterator>
#include <spirv-tools/libspirv.hpp>

#include <vulkan/utility/vk_format_utils.h>
#include <vulkan/utility/vk_struct_helper.hpp>

#include "shader_helper.h"
#include "sync_helper.h"
#include "shader_object_helper.h"

#define NON_DISPATCHABLE_HANDLE_INIT(create_func, dev, ...)                                                \
    do {                                                                                                   \
        assert(!initialized());                                                                            \
        handle_type handle;                                                                                \
        auto result = create_func(dev.handle(), __VA_ARGS__, nullptr, &handle);                            \
        ASSERT_TRUE((result == VK_SUCCESS) || (result == VK_ERROR_VALIDATION_FAILED_EXT) ||                \
                    (result == VK_ERROR_OUT_OF_DEVICE_MEMORY) || (result == VK_ERROR_OUT_OF_HOST_MEMORY)); \
        if (result == VK_SUCCESS) {                                                                        \
            NonDispHandle::init(dev.handle(), handle);                                                     \
        }                                                                                                  \
    } while (0)

#define NON_DISPATCHABLE_HANDLE_DTOR(cls, destroy_func)        \
    void cls::Destroy() noexcept {                             \
        if (!initialized()) {                                  \
            return;                                            \
        }                                                      \
        destroy_func(device(), handle(), NULL);                \
        handle_ = VK_NULL_HANDLE;                              \
        internal::NonDispHandle<decltype(handle_)>::Destroy(); \
    }                                                          \
    cls::~cls() noexcept { Destroy(); }

namespace vkt {

void Instance::Init(const VkInstanceCreateInfo& info) { ASSERT_EQ(VK_SUCCESS, vk::CreateInstance(&info, NULL, &handle_)); }

void Instance::Destroy() noexcept {
    if (handle_ != VK_NULL_HANDLE) {
        vk::DestroyInstance(handle_, nullptr);
        handle_ = VK_NULL_HANDLE;
    }
}

VkPhysicalDeviceProperties PhysicalDevice::Properties() const {
    VkPhysicalDeviceProperties info;
    vk::GetPhysicalDeviceProperties(handle(), &info);
    return info;
}

std::vector<VkQueueFamilyProperties> PhysicalDevice::QueueProperties() const {
    uint32_t count = 0;
    vk::GetPhysicalDeviceQueueFamilyProperties(handle(), &count, nullptr);
    std::vector<VkQueueFamilyProperties> info(count);
    vk::GetPhysicalDeviceQueueFamilyProperties(handle(), &count, info.data());
    return info;
}

VkPhysicalDeviceMemoryProperties PhysicalDevice::MemoryProperties() const {
    VkPhysicalDeviceMemoryProperties info;
    vk::GetPhysicalDeviceMemoryProperties(handle(), &info);
    return info;
}

VkPhysicalDeviceFeatures PhysicalDevice::Features() const {
    VkPhysicalDeviceFeatures features;
    vk::GetPhysicalDeviceFeatures(handle(), &features);
    return features;
}

/*
 * Return list of Global layers available
 */
std::vector<VkLayerProperties> GetGlobalLayers() {
    VkResult err;
    uint32_t layer_count = 32;
    std::vector<VkLayerProperties> layers(layer_count);
    for (;;) {
        err = vk::EnumerateInstanceLayerProperties(&layer_count, layers.data());
        if (err == VK_SUCCESS) {
            layers.resize(layer_count);
            return layers;
        } else if (err == VK_INCOMPLETE) {
            layer_count *= 2;  // wasn't enough space, increase it
            layers.resize(layer_count);
        } else {
            return {};
        }
    }
}

/*
 * Return list of Global extensions provided by the ICD / Loader
 */
std::vector<VkExtensionProperties> GetGlobalExtensions() { return GetGlobalExtensions(nullptr); }

/*
 * Return list of Global extensions provided by the specified layer
 * If pLayerName is NULL, will return extensions implemented by the loader /
 * ICDs
 */
std::vector<VkExtensionProperties> GetGlobalExtensions(const char* pLayerName) {
    VkResult err;
    uint32_t extension_count = 32;
    std::vector<VkExtensionProperties> extensions(extension_count);
    for (;;) {
        err = vk::EnumerateInstanceExtensionProperties(pLayerName, &extension_count, extensions.data());
        if (err == VK_SUCCESS) {
            extensions.resize(extension_count);
            return extensions;
        } else if (err == VK_INCOMPLETE) {
            extension_count *= 2;  // wasn't enough space, increase it
            extensions.resize(extension_count);
        } else {
            return {};
        }
    }
}

/*
 * Return list of PhysicalDevice extensions provided by the specified layer
 * If pLayerName is NULL, will return extensions for ICD / loader.
 */
std::vector<VkExtensionProperties> PhysicalDevice::Extensions(const char* pLayerName) const {
    VkResult err;
    uint32_t extension_count = 512;
    std::vector<VkExtensionProperties> extensions(extension_count);
    for (;;) {
        err = vk::EnumerateDeviceExtensionProperties(handle(), pLayerName, &extension_count, extensions.data());
        if (err == VK_SUCCESS) {
            extensions.resize(extension_count);
            return extensions;
        } else if (err == VK_INCOMPLETE) {
            extension_count *= 2;  // wasn't enough space, increase it
            extensions.resize(extension_count);
        } else {
            return {};
        }
    }
}

bool PhysicalDevice::SetMemoryType(const uint32_t type_bits, VkMemoryAllocateInfo* info, const VkFlags properties,
                                   const VkFlags forbid, const VkMemoryHeapFlags heapFlags) const {
    uint32_t type_mask = type_bits;
    // Search memtypes to find first index with those properties
    for (uint32_t i = 0; i < memory_properties_.memoryTypeCount; i++) {
        if ((type_mask & 1) == 1) {
            // Type is available, does it match user properties?
            if ((memory_properties_.memoryTypes[i].propertyFlags & properties) == properties &&
                (memory_properties_.memoryTypes[i].propertyFlags & forbid) == 0 &&
                (memory_properties_.memoryHeaps[memory_properties_.memoryTypes[i].heapIndex].size >= info->allocationSize)) {
                // Memory properties available, does it match user heap flags?
                if ((heapFlags == 0) ||
                    ((heapFlags & memory_properties_.memoryHeaps[memory_properties_.memoryTypes[i].heapIndex].flags) ==
                     heapFlags)) {
                    info->memoryTypeIndex = i;
                    return true;
                }
            }
        }
        type_mask >>= 1;
    }
    // No memory types matched, return failure
    return false;
}

/*
 * Return list of PhysicalDevice layers
 */
std::vector<VkLayerProperties> PhysicalDevice::Layers() const {
    VkResult err;
    uint32_t layer_count = 32;
    std::vector<VkLayerProperties> layers(layer_count);
    for (;;) {
        err = vk::EnumerateDeviceLayerProperties(handle(), &layer_count, layers.data());
        if (err == VK_SUCCESS) {
            layers.resize(layer_count);
            return layers;
        } else if (err == VK_INCOMPLETE) {
            layer_count *= 2;  // wasn't enough space, increase it
            layers.resize(layer_count);
        } else {
            return {};
        }
    }
}

QueueCreateInfoArray::QueueCreateInfoArray(const std::vector<VkQueueFamilyProperties>& queue_props, bool all_queue_count)
    : queue_info_(), queue_priorities_() {
    queue_info_.reserve(queue_props.size());

    for (uint32_t i = 0; i < (uint32_t)queue_props.size(); ++i) {
        if (queue_props[i].queueCount > 0) {
            VkDeviceQueueCreateInfo qi = vku::InitStructHelper();
            qi.queueFamilyIndex = i;
            // It is very slow on some drivers (ex Windows NVIDIA) to create all 16/32 queues supported
            qi.queueCount = all_queue_count ? queue_props[i].queueCount : 1;
            queue_priorities_.emplace_back(qi.queueCount, 0.0f);
            qi.pQueuePriorities = queue_priorities_[i].data();
            queue_info_.push_back(qi);
        }
    }
}

void Device::Destroy() noexcept {
    if (!initialized()) {
        return;
    }
    vk::DestroyDevice(handle(), nullptr);
    handle_ = VK_NULL_HANDLE;
}

Device::~Device() noexcept { Destroy(); }

void Device::Init(std::vector<const char*>& extensions, VkPhysicalDeviceFeatures* features, void* create_device_pnext,
                  bool all_queue_count) {
    // request all queues
    QueueCreateInfoArray queue_info(physical_device_.queue_properties_, all_queue_count);
    for (uint32_t i = 0; i < (uint32_t)physical_device_.queue_properties_.size(); i++) {
        if (physical_device_.queue_properties_[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
            graphics_queue_node_index_ = i;
            break;
        }
    }
    // Only request creation with queuefamilies that have at least one queue
    std::vector<VkDeviceQueueCreateInfo> create_queue_infos;
    auto qci = queue_info.Data();
    for (uint32_t j = 0; j < queue_info.Size(); ++j) {
        if (qci[j].queueCount) {
            create_queue_infos.push_back(qci[j]);
        }
    }

    enabled_extensions_ = extensions;

    VkDeviceCreateInfo dev_info = vku::InitStructHelper(create_device_pnext);
    dev_info.queueCreateInfoCount = static_cast<uint32_t>(create_queue_infos.size());
    dev_info.pQueueCreateInfos = create_queue_infos.data();
    dev_info.enabledLayerCount = 0;
    dev_info.ppEnabledLayerNames = NULL;
    dev_info.enabledExtensionCount = static_cast<uint32_t>(extensions.size());
    dev_info.ppEnabledExtensionNames = extensions.data();

    VkPhysicalDeviceFeatures all_features;
    // Let VkPhysicalDeviceFeatures2 take priority over VkPhysicalDeviceFeatures,
    // since it supports extensions

    if (auto features2 = vku::FindStructInPNextChain<VkPhysicalDeviceFeatures2>(dev_info.pNext)) {
        features_ = features2->features;
    } else {
        if (features) {
            dev_info.pEnabledFeatures = features;
        } else {
            // request all supportable features enabled
            all_features = Physical().Features();
            dev_info.pEnabledFeatures = &all_features;
        }
        features_ = *dev_info.pEnabledFeatures;
    }

    Init(dev_info);
}

void Device::Init(const VkDeviceCreateInfo& info) {
    VkDevice dev;

    ASSERT_EQ(VK_SUCCESS, vk::CreateDevice(physical_device_, &info, nullptr, &dev));
    Handle::init(dev);

    InitQueues(info);
}

void Device::InitQueues(const VkDeviceCreateInfo& info) {
    uint32_t queue_node_count = physical_device_.queue_properties_.size();

    queue_families_.resize(queue_node_count);
    for (uint32_t i = 0; i < info.queueCreateInfoCount; i++) {
        const auto& queue_create_info = info.pQueueCreateInfos[i];
        auto queue_family_i = queue_create_info.queueFamilyIndex;
        const auto& queue_family_prop = physical_device_.queue_properties_[queue_family_i];

        QueueFamilyQueues& queue_storage = queue_families_[queue_family_i];
        queue_storage.reserve(queue_create_info.queueCount);
        for (uint32_t queue_i = 0; queue_i < queue_create_info.queueCount; ++queue_i) {
            VkQueue queue = VK_NULL_HANDLE;
            if (queue_create_info.flags) {
                VkDeviceQueueInfo2 queue_info = vku::InitStructHelper();
                queue_info.flags = queue_create_info.flags;
                queue_info.queueFamilyIndex = queue_family_i;
                queue_info.queueIndex = queue_i;
                vk::GetDeviceQueue2(handle(), &queue_info, &queue);
            } else {
                vk::GetDeviceQueue(handle(), queue_family_i, queue_i, &queue);
            }

            // Store single copy of the queue object that will self destruct
            queue_storage.emplace_back(new Queue(queue, queue_family_i));

            if (queue_family_prop.queueFlags & VK_QUEUE_GRAPHICS_BIT) {
                queues_[GRAPHICS].push_back(queue_storage.back().get());
            }

            if (queue_family_prop.queueFlags & VK_QUEUE_COMPUTE_BIT) {
                queues_[COMPUTE].push_back(queue_storage.back().get());
            }

            if (queue_family_prop.queueFlags & VK_QUEUE_TRANSFER_BIT) {
                queues_[TRANSFER].push_back(queue_storage.back().get());
            }

            if (queue_family_prop.queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) {
                queues_[SPARSE].push_back(queue_storage.back().get());
            }

            if (queue_family_prop.queueFlags & VK_QUEUE_VIDEO_DECODE_BIT_KHR) {
                queues_[VIDEO_DECODE].push_back(queue_storage.back().get());
            }

            if (queue_family_prop.queueFlags & VK_QUEUE_VIDEO_ENCODE_BIT_KHR) {
                queues_[VIDEO_ENCODE].push_back(queue_storage.back().get());
            }

            if (queue_family_prop.queueFlags & VK_QUEUE_DATA_GRAPH_BIT_ARM) {
                queues_[DATA_GRAPH].push_back(queue_storage.back().get());
            }
        }
    }
}

const Device::QueueFamilyQueues& Device::QueuesFromFamily(uint32_t queue_family) const {
    assert(queue_family < queue_families_.size());
    return queue_families_[queue_family];
}

std::optional<uint32_t> Device::QueueFamily(VkQueueFlags with, VkQueueFlags without) const {
    for (uint32_t i = 0; i < physical_device_.queue_properties_.size(); i++) {
        if (physical_device_.queue_properties_[i].queueCount > 0) {
            const auto flags = physical_device_.queue_properties_[i].queueFlags;
            const bool matches = (flags & with) == with;
            if (matches && ((flags & without) == 0)) {
                return i;
            }
        }
    }
    return {};
}

std::optional<uint32_t> Device::QueueFamilyWithoutCapabilities(VkQueueFlags without) const {
    for (uint32_t i = 0; i < physical_device_.queue_properties_.size(); i++) {
        if (physical_device_.queue_properties_[i].queueCount > 0) {
            const auto flags = physical_device_.queue_properties_[i].queueFlags;
            if ((flags & without) == 0) {
                return i;
            }
        }
    }
    return {};
}

Queue* Device::QueueWithoutCapabilities(VkQueueFlags without) const {
    auto family_index = QueueFamilyWithoutCapabilities(without);
    return family_index.has_value() ? QueuesFromFamily(*family_index)[0].get() : nullptr;
}

std::optional<uint32_t> Device::ComputeOnlyQueueFamily() const { return QueueFamily(VK_QUEUE_COMPUTE_BIT, VK_QUEUE_GRAPHICS_BIT); }

Queue* Device::ComputeOnlyQueue() const {
    auto family_index = ComputeOnlyQueueFamily();
    return family_index.has_value() ? QueuesFromFamily(*family_index)[0].get() : nullptr;
}

std::optional<uint32_t> Device::TransferOnlyQueueFamily() const {
    return QueueFamily(VK_QUEUE_TRANSFER_BIT, VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT);
}

Queue* Device::TransferOnlyQueue() const {
    auto family_index = TransferOnlyQueueFamily();
    return family_index.has_value() ? QueuesFromFamily(*family_index)[0].get() : nullptr;
}

std::optional<uint32_t> Device::NonGraphicsQueueFamily() const {
    if (auto compute_qfi = ComputeOnlyQueueFamily(); compute_qfi.has_value()) {
        return compute_qfi;
    }
    return TransferOnlyQueueFamily();
}

Queue* Device::NonGraphicsQueue() const {
    auto family_index = NonGraphicsQueueFamily();
    return family_index.has_value() ? QueuesFromFamily(*family_index)[0].get() : nullptr;
}

bool Device::IsEnabledExtension(const char* extension) const {
    const auto is_x = [&extension](const char* enabled_extension) { return strcmp(extension, enabled_extension) == 0; };
    return std::any_of(enabled_extensions_.begin(), enabled_extensions_.end(), is_x);
}

VkFormatFeatureFlags2 Device::FormatFeaturesLinear(VkFormat format) const {
    if (IsEnabledExtension(VK_KHR_FORMAT_FEATURE_FLAGS_2_EXTENSION_NAME)) {
        VkFormatProperties3 fmt_props_3 = vku::InitStructHelper();
        VkFormatProperties2 fmt_props_2 = vku::InitStructHelper(&fmt_props_3);
        vk::GetPhysicalDeviceFormatProperties2(Physical(), format, &fmt_props_2);
        return fmt_props_3.linearTilingFeatures;
    } else {
        VkFormatProperties format_properties;
        vk::GetPhysicalDeviceFormatProperties(Physical(), format, &format_properties);
        return format_properties.linearTilingFeatures;
    }
}

VkFormatFeatureFlags2 Device::FormatFeaturesOptimal(VkFormat format) const {
    if (IsEnabledExtension(VK_KHR_FORMAT_FEATURE_FLAGS_2_EXTENSION_NAME)) {
        VkFormatProperties3 fmt_props_3 = vku::InitStructHelper();
        VkFormatProperties2 fmt_props_2 = vku::InitStructHelper(&fmt_props_3);
        vk::GetPhysicalDeviceFormatProperties2(Physical(), format, &fmt_props_2);
        return fmt_props_3.optimalTilingFeatures;
    } else {
        VkFormatProperties format_properties;
        vk::GetPhysicalDeviceFormatProperties(Physical(), format, &format_properties);
        return format_properties.optimalTilingFeatures;
    }
}

VkFormatFeatureFlags2 Device::FormatFeaturesBuffer(VkFormat format) const {
    if (IsEnabledExtension(VK_KHR_FORMAT_FEATURE_FLAGS_2_EXTENSION_NAME)) {
        VkFormatProperties3 fmt_props_3 = vku::InitStructHelper();
        VkFormatProperties2 fmt_props_2 = vku::InitStructHelper(&fmt_props_3);
        vk::GetPhysicalDeviceFormatProperties2(Physical(), format, &fmt_props_2);
        return fmt_props_3.bufferFeatures;
    } else {
        VkFormatProperties format_properties;
        vk::GetPhysicalDeviceFormatProperties(Physical(), format, &format_properties);
        return format_properties.bufferFeatures;
    }
}

void Device::Wait() const { ASSERT_EQ(VK_SUCCESS, vk::DeviceWaitIdle(handle())); }

VkResult Device::Wait(const std::vector<const Fence*>& fences, bool wait_all, uint64_t timeout) {
    std::vector<VkFence> fence_handles;
    fence_handles.reserve(fences.size());
    std::transform(fences.begin(), fences.end(), std::back_inserter(fence_handles),
                   [](const Fence* o) { return (o) ? o->handle() : VK_NULL_HANDLE; });

    VkResult err =
        vk::WaitForFences(handle(), static_cast<uint32_t>(fence_handles.size()), fence_handles.data(), wait_all, timeout);
    EXPECT_TRUE(err == VK_SUCCESS || err == VK_TIMEOUT);

    return err;
}

VkResult Queue::Submit(const CommandBuffer& cmd, const Fence& fence) {
    VkSubmitInfo submit = vku::InitStructHelper();
    submit.commandBufferCount = cmd.initialized() ? 1 : 0;
    submit.pCommandBuffers = &cmd.handle();
    VkResult result = vk::QueueSubmit(handle(), 1, &submit, fence);
    return result;
}

VkResult Queue::Submit(const std::vector<VkCommandBuffer>& cmds, const Fence& fence) {
    VkSubmitInfo submit_info = vku::InitStructHelper();
    submit_info.commandBufferCount = static_cast<uint32_t>(cmds.size());
    submit_info.pCommandBuffers = cmds.data();
    VkResult result = vk::QueueSubmit(handle(), 1, &submit_info, fence);
    return result;
}

VkResult Queue::Submit(const CommandBuffer& cmd, const vkt::Wait& wait, const Fence& fence) {
    assert(wait.stage_mask < VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM);
    const auto wait_stage_mask = static_cast<VkPipelineStageFlags>(wait.stage_mask);

    VkSubmitInfo submit = vku::InitStructHelper();
    submit.waitSemaphoreCount = 1;
    submit.pWaitSemaphores = &wait.semaphore.handle();
    submit.pWaitDstStageMask = &wait_stage_mask;
    submit.commandBufferCount = cmd.initialized() ? 1 : 0;
    submit.pCommandBuffers = &cmd.handle();
    VkResult result = vk::QueueSubmit(handle(), 1, &submit, fence);
    return result;
}

VkResult Queue::Submit(const CommandBuffer& cmd, const Signal& signal, const Fence& fence) {
    assert(signal.stage_mask == VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);

    VkSubmitInfo submit = vku::InitStructHelper();
    submit.commandBufferCount = cmd.initialized() ? 1 : 0;
    submit.pCommandBuffers = &cmd.handle();
    submit.signalSemaphoreCount = 1;
    submit.pSignalSemaphores = &signal.semaphore.handle();
    VkResult result = vk::QueueSubmit(handle(), 1, &submit, fence);
    return result;
}

VkResult Queue::Submit(const CommandBuffer& cmd, const vkt::Wait& wait, const Signal& signal, const Fence& fence) {
    assert(wait.stage_mask < VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM);
    assert(signal.stage_mask == VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
    const auto wait_stage_mask = static_cast<VkPipelineStageFlags>(wait.stage_mask);

    VkSubmitInfo submit = vku::InitStructHelper();
    submit.waitSemaphoreCount = 1;
    submit.pWaitSemaphores = &wait.semaphore.handle();
    submit.pWaitDstStageMask = &wait_stage_mask;
    submit.commandBufferCount = cmd.initialized() ? 1 : 0;
    submit.pCommandBuffers = &cmd.handle();
    submit.signalSemaphoreCount = 1;
    submit.pSignalSemaphores = &signal.semaphore.handle();
    VkResult result = vk::QueueSubmit(handle(), 1, &submit, fence);
    return result;
}

VkResult Queue::Submit(const CommandBuffer& cmd, const TimelineWait& wait, const Fence& fence) {
    assert(wait.stage_mask < VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM);
    const auto wait_stage_mask = static_cast<VkPipelineStageFlags>(wait.stage_mask);

    VkTimelineSemaphoreSubmitInfo timeline_info = vku::InitStructHelper();
    timeline_info.waitSemaphoreValueCount = 1;
    timeline_info.pWaitSemaphoreValues = &wait.value;

    VkSubmitInfo submit = vku::InitStructHelper(&timeline_info);
    submit.waitSemaphoreCount = 1;
    submit.pWaitSemaphores = &wait.semaphore.handle();
    submit.pWaitDstStageMask = &wait_stage_mask;
    submit.commandBufferCount = cmd.initialized() ? 1 : 0;
    submit.pCommandBuffers = &cmd.handle();
    VkResult result = vk::QueueSubmit(handle(), 1, &submit, fence);
    return result;
}

VkResult Queue::Submit(const CommandBuffer& cmd, const TimelineSignal& signal, const Fence& fence) {
    assert(signal.stage_mask == VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);

    VkTimelineSemaphoreSubmitInfo timeline_info = vku::InitStructHelper();
    timeline_info.signalSemaphoreValueCount = 1;
    timeline_info.pSignalSemaphoreValues = &signal.value;

    VkSubmitInfo submit = vku::InitStructHelper(&timeline_info);
    submit.commandBufferCount = cmd.initialized() ? 1 : 0;
    submit.pCommandBuffers = &cmd.handle();
    submit.signalSemaphoreCount = 1;
    submit.pSignalSemaphores = &signal.semaphore.handle();
    VkResult result = vk::QueueSubmit(handle(), 1, &submit, fence);
    return result;
}

VkResult Queue::Submit(const CommandBuffer& cmd, const TimelineWait& wait, const TimelineSignal& signal, const Fence& fence) {
    assert(wait.stage_mask < VK_PIPELINE_STAGE_FLAG_BITS_MAX_ENUM);
    assert(signal.stage_mask == VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
    const auto wait_stage_mask = static_cast<VkPipelineStageFlags>(wait.stage_mask);

    VkTimelineSemaphoreSubmitInfo timeline_info = vku::InitStructHelper();
    timeline_info.waitSemaphoreValueCount = 1;
    timeline_info.pWaitSemaphoreValues = &wait.value;
    timeline_info.signalSemaphoreValueCount = 1;
    timeline_info.pSignalSemaphoreValues = &signal.value;

    VkSubmitInfo submit = vku::InitStructHelper(&timeline_info);
    submit.waitSemaphoreCount = 1;
    submit.pWaitSemaphores = &wait.semaphore.handle();
    submit.pWaitDstStageMask = &wait_stage_mask;
    submit.commandBufferCount = cmd.initialized() ? 1 : 0;
    submit.pCommandBuffers = &cmd.handle();
    submit.signalSemaphoreCount = 1;
    submit.pSignalSemaphores = &signal.semaphore.handle();
    VkResult result = vk::QueueSubmit(handle(), 1, &submit, fence);
    return result;
}

VkResult Queue::Submit2(const CommandBuffer& cmd, const Fence& fence, bool use_khr) {
    VkCommandBufferSubmitInfo cb_info = vku::InitStructHelper();
    cb_info.commandBuffer = cmd;

    VkSubmitInfo2 submit = vku::InitStructHelper();
    submit.commandBufferInfoCount = cmd.initialized() ? 1 : 0;
    submit.pCommandBufferInfos = &cb_info;

    VkResult result;
    if (use_khr) {
        result = vk::QueueSubmit2KHR(handle(), 1, &submit, fence);
    } else {
        result = vk::QueueSubmit2(handle(), 1, &submit, fence);
    }
    return result;
}

VkResult Queue::Submit2(const std::vector<VkCommandBuffer>& cmds, const Fence& fence, bool use_khr) {
    std::vector<VkCommandBufferSubmitInfo> cmd_submit_infos;
    cmd_submit_infos.reserve(cmds.size());
    for (size_t i = 0; i < cmds.size(); i++) {
        VkCommandBufferSubmitInfo cmd_submit_info = vku::InitStructHelper();
        cmd_submit_info.commandBuffer = cmds[i];
        cmd_submit_infos.push_back(cmd_submit_info);
    }
    VkSubmitInfo2 submit = vku::InitStructHelper();
    submit.commandBufferInfoCount = static_cast<uint32_t>(cmd_submit_infos.size());
    submit.pCommandBufferInfos = cmd_submit_infos.data();

    VkResult result;
    if (use_khr) {
        result = vk::QueueSubmit2KHR(handle(), 1, &submit, fence);
    } else {
        result = vk::QueueSubmit2(handle(), 1, &submit, fence);
    }
    return result;
}

VkResult Queue::Submit2(const CommandBuffer& cmd, const vkt::Wait& wait, const Fence& fence, bool use_khr) {
    VkCommandBufferSubmitInfo cb_info = vku::InitStructHelper();
    cb_info.commandBuffer = cmd;

    VkSemaphoreSubmitInfo wait_info = vku::InitStructHelper();
    wait_info.semaphore = wait.semaphore;
    wait_info.stageMask = wait.stage_mask;

    VkSubmitInfo2 submit = vku::InitStructHelper();
    submit.waitSemaphoreInfoCount = 1;
    submit.pWaitSemaphoreInfos = &wait_info;
    submit.commandBufferInfoCount = cmd.initialized() ? 1 : 0;
    submit.pCommandBufferInfos = &cb_info;

    VkResult result;
    if (use_khr) {
        result = vk::QueueSubmit2KHR(handle(), 1, &submit, fence);
    } else {
        result = vk::QueueSubmit2(handle(), 1, &submit, fence);
    }
    return result;
}

VkResult Queue::Submit2(const CommandBuffer& cmd, const Signal& signal, const Fence& fence, bool use_khr) {
    VkCommandBufferSubmitInfo cb_info = vku::InitStructHelper();
    cb_info.commandBuffer = cmd;

    VkSemaphoreSubmitInfo signal_info = vku::InitStructHelper();
    signal_info.semaphore = signal.semaphore;
    signal_info.stageMask = signal.stage_mask;

    VkSubmitInfo2 submit = vku::InitStructHelper();
    submit.commandBufferInfoCount = cmd.initialized() ? 1 : 0;
    submit.pCommandBufferInfos = &cb_info;
    submit.signalSemaphoreInfoCount = 1;
    submit.pSignalSemaphoreInfos = &signal_info;

    VkResult result;
    if (use_khr) {
        result = vk::QueueSubmit2KHR(handle(), 1, &submit, fence);
    } else {
        result = vk::QueueSubmit2(handle(), 1, &submit, fence);
    }
    return result;
}

VkResult Queue::Submit2(const CommandBuffer& cmd, const vkt::Wait& wait, const Signal& signal, const Fence& fence, bool use_khr) {
    VkCommandBufferSubmitInfo cb_info = vku::InitStructHelper();
    cb_info.commandBuffer = cmd;

    VkSemaphoreSubmitInfo wait_info = vku::InitStructHelper();
    wait_info.semaphore = wait.semaphore;
    wait_info.stageMask = wait.stage_mask;

    VkSemaphoreSubmitInfo signal_info = vku::InitStructHelper();
    signal_info.semaphore = signal.semaphore;
    signal_info.stageMask = signal.stage_mask;

    VkSubmitInfo2 submit = vku::InitStructHelper();
    submit.waitSemaphoreInfoCount = 1;
    submit.pWaitSemaphoreInfos = &wait_info;
    submit.commandBufferInfoCount = cmd.initialized() ? 1 : 0;
    submit.pCommandBufferInfos = &cb_info;
    submit.signalSemaphoreInfoCount = 1;
    submit.pSignalSemaphoreInfos = &signal_info;

    VkResult result;
    if (use_khr) {
        result = vk::QueueSubmit2KHR(handle(), 1, &submit, fence);
    } else {
        result = vk::QueueSubmit2(handle(), 1, &submit, fence);
    }
    return result;
}

VkResult Queue::Submit2(const CommandBuffer& cmd, const TimelineWait& wait, const Fence& fence, bool use_khr) {
    VkCommandBufferSubmitInfo cb_info = vku::InitStructHelper();
    cb_info.commandBuffer = cmd;

    VkSemaphoreSubmitInfo wait_info = vku::InitStructHelper();
    wait_info.semaphore = wait.semaphore;
    wait_info.value = wait.value;
    wait_info.stageMask = wait.stage_mask;

    VkSubmitInfo2 submit = vku::InitStructHelper();
    submit.waitSemaphoreInfoCount = 1;
    submit.pWaitSemaphoreInfos = &wait_info;
    submit.commandBufferInfoCount = cmd.initialized() ? 1 : 0;
    submit.pCommandBufferInfos = &cb_info;

    VkResult result;
    if (use_khr) {
        result = vk::QueueSubmit2KHR(handle(), 1, &submit, fence);
    } else {
        result = vk::QueueSubmit2(handle(), 1, &submit, fence);
    }
    return result;
}

VkResult Queue::Submit2(const CommandBuffer& cmd, const TimelineSignal& signal, const Fence& fence, bool use_khr) {
    VkCommandBufferSubmitInfo cb_info = vku::InitStructHelper();
    cb_info.commandBuffer = cmd;

    VkSemaphoreSubmitInfo signal_info = vku::InitStructHelper();
    signal_info.semaphore = signal.semaphore;
    signal_info.value = signal.value;
    signal_info.stageMask = signal.stage_mask;

    VkSubmitInfo2 submit = vku::InitStructHelper();
    submit.commandBufferInfoCount = cmd.initialized() ? 1 : 0;
    submit.pCommandBufferInfos = &cb_info;
    submit.signalSemaphoreInfoCount = 1;
    submit.pSignalSemaphoreInfos = &signal_info;

    VkResult result;
    if (use_khr) {
        result = vk::QueueSubmit2KHR(handle(), 1, &submit, fence);
    } else {
        result = vk::QueueSubmit2(handle(), 1, &submit, fence);
    }
    return result;
}

VkResult Queue::Submit2(const CommandBuffer& cmd, const TimelineWait& wait, const TimelineSignal& signal, const Fence& fence,
                        bool use_khr) {
    VkCommandBufferSubmitInfo cb_info = vku::InitStructHelper();
    cb_info.commandBuffer = cmd;

    VkSemaphoreSubmitInfo wait_info = vku::InitStructHelper();
    wait_info.semaphore = wait.semaphore;
    wait_info.value = wait.value;
    wait_info.stageMask = wait.stage_mask;

    VkSemaphoreSubmitInfo signal_info = vku::InitStructHelper();
    signal_info.semaphore = signal.semaphore;
    signal_info.value = signal.value;
    signal_info.stageMask = signal.stage_mask;

    VkSubmitInfo2 submit = vku::InitStructHelper();
    submit.waitSemaphoreInfoCount = 1;
    submit.pWaitSemaphoreInfos = &wait_info;
    submit.commandBufferInfoCount = cmd.initialized() ? 1 : 0;
    submit.pCommandBufferInfos = &cb_info;
    submit.signalSemaphoreInfoCount = 1;
    submit.pSignalSemaphoreInfos = &signal_info;

    VkResult result;
    if (use_khr) {
        result = vk::QueueSubmit2KHR(handle(), 1, &submit, fence);
    } else {
        result = vk::QueueSubmit2(handle(), 1, &submit, fence);
    }
    return result;
}

VkResult Queue::Submit2(const CommandBuffer& cmd, const vkt::Wait& wait, const TimelineSignal& signal, const Fence& fence) {
    VkCommandBufferSubmitInfo cb_info = vku::InitStructHelper();
    cb_info.commandBuffer = cmd;

    VkSemaphoreSubmitInfo wait_info = vku::InitStructHelper();
    wait_info.semaphore = wait.semaphore;
    wait_info.stageMask = wait.stage_mask;

    VkSemaphoreSubmitInfo signal_info = vku::InitStructHelper();
    signal_info.semaphore = signal.semaphore;
    signal_info.value = signal.value;
    signal_info.stageMask = signal.stage_mask;

    VkSubmitInfo2 submit = vku::InitStructHelper();
    submit.waitSemaphoreInfoCount = 1;
    submit.pWaitSemaphoreInfos = &wait_info;
    submit.commandBufferInfoCount = cmd.initialized() ? 1 : 0;
    submit.pCommandBufferInfos = &cb_info;
    submit.signalSemaphoreInfoCount = 1;
    submit.pSignalSemaphoreInfos = &signal_info;

    VkResult result = vk::QueueSubmit2(handle(), 1, &submit, fence);
    return result;
}

VkResult Queue::Submit2(const CommandBuffer& cmd, const TimelineWait& wait, const Signal& signal, const Fence& fence) {
    VkCommandBufferSubmitInfo cb_info = vku::InitStructHelper();
    cb_info.commandBuffer = cmd;

    VkSemaphoreSubmitInfo wait_info = vku::InitStructHelper();
    wait_info.semaphore = wait.semaphore;
    wait_info.value = wait.value;
    wait_info.stageMask = wait.stage_mask;

    VkSemaphoreSubmitInfo signal_info = vku::InitStructHelper();
    signal_info.semaphore = signal.semaphore;
    signal_info.stageMask = signal.stage_mask;

    VkSubmitInfo2 submit = vku::InitStructHelper();
    submit.waitSemaphoreInfoCount = 1;
    submit.pWaitSemaphoreInfos = &wait_info;
    submit.commandBufferInfoCount = cmd.initialized() ? 1 : 0;
    submit.pCommandBufferInfos = &cb_info;
    submit.signalSemaphoreInfoCount = 1;
    submit.pSignalSemaphoreInfos = &signal_info;

    VkResult result = vk::QueueSubmit2(handle(), 1, &submit, fence);
    return result;
}

VkResult Queue::Present(const Swapchain& swapchain, uint32_t image_index, const Semaphore& wait_semaphore,
                        void* present_info_pnext) {
    VkPresentInfoKHR present = vku::InitStructHelper(present_info_pnext);
    if (wait_semaphore.initialized()) {
        present.waitSemaphoreCount = 1;
        present.pWaitSemaphores = &wait_semaphore.handle();
    }
    present.swapchainCount = 1;
    present.pSwapchains = &swapchain.handle();
    present.pImageIndices = &image_index;
    VkResult result = vk::QueuePresentKHR(handle(), &present);
    return result;
}

VkResult Queue::Wait() {
    VkResult result = vk::QueueWaitIdle(handle());
    EXPECT_EQ(VK_SUCCESS, result);
    return result;
}

void DeviceMemory::Destroy() noexcept {
    if (!initialized()) {
        return;
    }

    vk::FreeMemory(device(), handle(), NULL);
    handle_ = VK_NULL_HANDLE;
}

DeviceMemory::~DeviceMemory() noexcept { Destroy(); }

void DeviceMemory::Init(const Device& dev, const VkMemoryAllocateInfo& info) {
    NON_DISPATCHABLE_HANDLE_INIT(vk::AllocateMemory, dev, &info);
    memory_allocate_info_ = info;
}

VkResult DeviceMemory::TryInit(const Device& dev, const VkMemoryAllocateInfo& info) {
    assert(!initialized());
    VkDeviceMemory handle = VK_NULL_HANDLE;
    auto result = vk::AllocateMemory(dev, &info, nullptr, &handle);
    if (result == VK_SUCCESS) {
        NonDispHandle::init(dev, handle);
    }
    return result;
}

const void* DeviceMemory::Map(VkFlags flags) const {
    void* data;
    VkResult result = vk::MapMemory(device(), handle(), 0, VK_WHOLE_SIZE, flags, &data);
    EXPECT_EQ(VK_SUCCESS, result);
    if (result != VK_SUCCESS) data = NULL;
    return data;
}

void* DeviceMemory::Map(VkFlags flags) {
    void* data;
    VkResult result = vk::MapMemory(device(), handle(), 0, VK_WHOLE_SIZE, flags, &data);
    EXPECT_EQ(VK_SUCCESS, result);
    if (result != VK_SUCCESS) data = NULL;

    return data;
}

void DeviceMemory::Unmap() const { vk::UnmapMemory(device(), handle()); }

VkMemoryAllocateInfo DeviceMemory::GetResourceAllocInfo(const Device& dev, const VkMemoryRequirements& reqs,
                                                        VkMemoryPropertyFlags mem_props, void* alloc_info_pnext) {
    VkMemoryAllocateInfo alloc_info = vku::InitStructHelper(alloc_info_pnext);
    alloc_info.allocationSize = reqs.size;
    EXPECT_TRUE(dev.Physical().SetMemoryType(reqs.memoryTypeBits, &alloc_info, mem_props));
    return alloc_info;
}

NON_DISPATCHABLE_HANDLE_DTOR(Fence, vk::DestroyFence)

Fence& Fence::operator=(Fence&& rhs) noexcept {
    Destroy();
    NonDispHandle<VkFence>::operator=(std::move(rhs));
    return *this;
}

void Fence::Init(const Device& dev, const VkFenceCreateInfo& info) { NON_DISPATCHABLE_HANDLE_INIT(vk::CreateFence, dev, &info); }

void Fence::Init(const Device& dev, const VkFenceCreateFlags flags) {
    VkFenceCreateInfo fence_ci = vku::InitStructHelper();
    fence_ci.flags = flags;
    Init(dev, fence_ci);
}

VkResult Fence::Wait(uint64_t timeout) const { return vk::WaitForFences(device(), 1, &handle(), VK_TRUE, timeout); }

VkResult Fence::Reset() const { return vk::ResetFences(device(), 1, &handle()); }

#ifdef VK_USE_PLATFORM_WIN32_KHR
VkResult Fence::ExportHandle(HANDLE& win32_handle, VkExternalFenceHandleTypeFlagBits handle_type) {
    VkFenceGetWin32HandleInfoKHR ghi = vku::InitStructHelper();
    ghi.fence = handle();
    ghi.handleType = handle_type;
    return vk::GetFenceWin32HandleKHR(device(), &ghi, &win32_handle);
}

VkResult Fence::ImportHandle(HANDLE win32_handle, VkExternalFenceHandleTypeFlagBits handle_type, VkFenceImportFlags flags) {
    VkImportFenceWin32HandleInfoKHR ifi = vku::InitStructHelper();
    ifi.fence = handle();
    ifi.handleType = handle_type;
    ifi.handle = win32_handle;
    ifi.flags = flags;
    return vk::ImportFenceWin32HandleKHR(device(), &ifi);
}
#endif  // VK_USE_PLATFORM_WIN32_KHR

VkResult Fence::ExportHandle(int& fd_handle, VkExternalFenceHandleTypeFlagBits handle_type) {
    VkFenceGetFdInfoKHR gfi = vku::InitStructHelper();
    gfi.fence = handle();
    gfi.handleType = handle_type;
    return vk::GetFenceFdKHR(device(), &gfi, &fd_handle);
}

VkResult Fence::ImportHandle(int fd_handle, VkExternalFenceHandleTypeFlagBits handle_type, VkFenceImportFlags flags) {
    VkImportFenceFdInfoKHR ifi = vku::InitStructHelper();
    ifi.fence = handle();
    ifi.handleType = handle_type;
    ifi.fd = fd_handle;
    ifi.flags = flags;
    return vk::ImportFenceFdKHR(device(), &ifi);
}

NON_DISPATCHABLE_HANDLE_DTOR(Semaphore, vk::DestroySemaphore)

Semaphore::Semaphore(const Device& dev, VkSemaphoreType type, uint64_t initial_value) {
    if (type == VK_SEMAPHORE_TYPE_BINARY) {
        Init(dev, vku::InitStruct<VkSemaphoreCreateInfo>());
    } else {
        VkSemaphoreTypeCreateInfo semaphore_type_ci = vku::InitStructHelper();
        semaphore_type_ci.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE;
        semaphore_type_ci.initialValue = initial_value;
        VkSemaphoreCreateInfo semaphore_ci = vku::InitStructHelper(&semaphore_type_ci);
        Init(dev, semaphore_ci);
    }
}

Semaphore& Semaphore::operator=(Semaphore&& rhs) noexcept {
    Destroy();
    NonDispHandle<VkSemaphore>::operator=(std::move(rhs));
    return *this;
}

void Semaphore::Init(const Device& dev, const VkSemaphoreCreateInfo& info) {
    NON_DISPATCHABLE_HANDLE_INIT(vk::CreateSemaphore, dev, &info);
}

VkResult Semaphore::Wait(uint64_t value, uint64_t timeout) {
    VkSemaphoreWaitInfo wait_info = vku::InitStructHelper();
    wait_info.semaphoreCount = 1;
    wait_info.pSemaphores = &handle();
    wait_info.pValues = &value;
    VkResult result = vk::WaitSemaphores(device(), &wait_info, timeout);
    return result;
}

VkResult Semaphore::WaitKHR(uint64_t value, uint64_t timeout) {
    VkSemaphoreWaitInfoKHR wait_info = vku::InitStructHelper();
    wait_info.semaphoreCount = 1;
    wait_info.pSemaphores = &handle();
    wait_info.pValues = &value;
    VkResult result = vk::WaitSemaphoresKHR(device(), &wait_info, timeout);
    return result;
}

VkResult Semaphore::Signal(uint64_t value) {
    VkSemaphoreSignalInfo signal_info = vku::InitStructHelper();
    signal_info.semaphore = handle();
    signal_info.value = value;
    VkResult result = vk::SignalSemaphore(device(), &signal_info);
    return result;
}

VkResult Semaphore::SignalKHR(uint64_t value) {
    VkSemaphoreSignalInfoKHR signal_info = vku::InitStructHelper();
    signal_info.semaphore = handle();
    signal_info.value = value;
    VkResult result = vk::SignalSemaphoreKHR(device(), &signal_info);
    return result;
}

uint64_t Semaphore::GetCounterValue(bool use_khr) const {
    uint64_t counter = 0;
    if (use_khr) {
        vk::GetSemaphoreCounterValueKHR(device(), handle(), &counter);
    } else {
        vk::GetSemaphoreCounterValue(device(), handle(), &counter);
    }
    return counter;
}

#ifdef VK_USE_PLATFORM_WIN32_KHR
VkResult Semaphore::ExportHandle(HANDLE& win32_handle, VkExternalSemaphoreHandleTypeFlagBits handle_type) {
    win32_handle = nullptr;
    VkSemaphoreGetWin32HandleInfoKHR ghi = vku::InitStructHelper();
    ghi.semaphore = handle();
    ghi.handleType = handle_type;
    return vk::GetSemaphoreWin32HandleKHR(device(), &ghi, &win32_handle);
}

VkResult Semaphore::ImportHandle(HANDLE win32_handle, VkExternalSemaphoreHandleTypeFlagBits handle_type,
                                 VkSemaphoreImportFlags flags) {
    VkImportSemaphoreWin32HandleInfoKHR ihi = vku::InitStructHelper();
    ihi.semaphore = handle();
    ihi.handleType = handle_type;
    ihi.handle = win32_handle;
    ihi.flags = flags;
    return vk::ImportSemaphoreWin32HandleKHR(device(), &ihi);
}
#endif  // VK_USE_PLATFORM_WIN32_KHR

VkResult Semaphore::ExportHandle(int& fd_handle, VkExternalSemaphoreHandleTypeFlagBits handle_type) {
    fd_handle = -1;
    VkSemaphoreGetFdInfoKHR ghi = vku::InitStructHelper();
    ghi.semaphore = handle();
    ghi.handleType = handle_type;
    return vk::GetSemaphoreFdKHR(device(), &ghi, &fd_handle);
}

VkResult Semaphore::ImportHandle(int fd_handle, VkExternalSemaphoreHandleTypeFlagBits handle_type, VkSemaphoreImportFlags flags) {
    // Import opaque handle exported above
    VkImportSemaphoreFdInfoKHR ihi = vku::InitStructHelper();
    ihi.semaphore = handle();
    ihi.handleType = handle_type;
    ihi.fd = fd_handle;
    ihi.flags = flags;
    return vk::ImportSemaphoreFdKHR(device(), &ihi);
}

NON_DISPATCHABLE_HANDLE_DTOR(Event, vk::DestroyEvent)

void Event::Init(const Device& dev, const VkEventCreateInfo& info) { NON_DISPATCHABLE_HANDLE_INIT(vk::CreateEvent, dev, &info); }

VkResult Event::GetStatus() const { return vk::GetEventStatus(device(), handle()); }
void Event::Set() { ASSERT_EQ(VK_SUCCESS, vk::SetEvent(device(), handle())); }
void Event::Reset() { ASSERT_EQ(VK_SUCCESS, vk::ResetEvent(device(), handle())); }

NON_DISPATCHABLE_HANDLE_DTOR(QueryPool, vk::DestroyQueryPool)

void QueryPool::Init(const Device& dev, const VkQueryPoolCreateInfo& info) {
    NON_DISPATCHABLE_HANDLE_INIT(vk::CreateQueryPool, dev, &info);
}

VkResult QueryPool::Results(uint32_t first, uint32_t count, size_t size, void* data, size_t stride) {
    VkResult err = vk::GetQueryPoolResults(device(), handle(), first, count, size, data, stride, 0);
    EXPECT_TRUE(err == VK_SUCCESS || err == VK_NOT_READY);

    return err;
}

NON_DISPATCHABLE_HANDLE_DTOR(Buffer, vk::DestroyBuffer)

Buffer::Buffer(Buffer&& rhs) noexcept : NonDispHandle(std::move(rhs)) {
    create_info_ = std::move(rhs.create_info_);
    internal_mem_ = std::move(rhs.internal_mem_);
}

Buffer& Buffer::operator=(Buffer&& rhs) noexcept {
    if (&rhs == this) {
        return *this;
    }
    Destroy();
    internal_mem_.Destroy();
    NonDispHandle::operator=(std::move(rhs));
    create_info_ = std::move(rhs.create_info_);
    internal_mem_ = std::move(rhs.internal_mem_);
    return *this;
}

void Buffer::Init(const Device& dev, const VkBufferCreateInfo& info, VkMemoryPropertyFlags mem_props, void* alloc_info_pnext) {
    InitNoMemory(dev, info);

    auto alloc_info = DeviceMemory::GetResourceAllocInfo(dev, MemoryRequirements(), mem_props, alloc_info_pnext);
    internal_mem_.Init(dev, alloc_info);

    BindMemory(internal_mem_, 0);
}

void Buffer::InitHostVisibleWithData(const Device& dev, VkBufferUsageFlags usage, const void* data, size_t data_size,
                                     const vvl::span<uint32_t>& queue_families) {
    const auto create_info = CreateInfo(static_cast<VkDeviceSize>(data_size), usage, queue_families);
    InitNoMemory(dev, create_info);

    // According to the specification there is always a host visible coherent memory type.
    // It can always be bound to a buffer created without SPARSE_BINDING/PROTECTED flags.
    const VkMemoryPropertyFlags memory_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT;
    const VkMemoryRequirements memory_requirements = MemoryRequirements();
    VkMemoryAllocateInfo alloc_info = vku::InitStructHelper();
    alloc_info.allocationSize = memory_requirements.size;
    dev.Physical().SetMemoryType(memory_requirements.memoryTypeBits, &alloc_info, memory_properties);
    internal_mem_.Init(dev, alloc_info);
    BindMemory(internal_mem_, 0);

    void* ptr = internal_mem_.Map();
    std::memcpy(ptr, data, data_size);
    internal_mem_.Unmap();
}

void Buffer::InitNoMemory(const Device& dev, const VkBufferCreateInfo& info) {
    NON_DISPATCHABLE_HANDLE_INIT(vk::CreateBuffer, dev, &info);
    create_info_ = info;
}

VkMemoryRequirements Buffer::MemoryRequirements() const {
    VkMemoryRequirements reqs;

    vk::GetBufferMemoryRequirements(device(), handle(), &reqs);

    return reqs;
}

void Buffer::AllocateAndBindMemory(const Device& dev, VkMemoryPropertyFlags mem_props, void* alloc_info_pnext) {
    assert(!internal_mem_.initialized());
    internal_mem_.Init(dev, DeviceMemory::GetResourceAllocInfo(dev, MemoryRequirements(), mem_props, alloc_info_pnext));
    BindMemory(internal_mem_, 0);
}

void Buffer::BindMemory(const DeviceMemory& mem, VkDeviceSize mem_offset) {
    const auto result = vk::BindBufferMemory(device(), handle(), mem, mem_offset);
    // Allow successful calls and the calls that cause validation errors (but not actual Vulkan errors).
    // In the case of a validation error, it's part of the test logic how to handle it.
    ASSERT_TRUE(result == VK_SUCCESS || result == VK_ERROR_VALIDATION_FAILED_EXT);
}

VkDeviceAddress Buffer::Address() const {
    VkBufferDeviceAddressInfo bdai = vku::InitStructHelper();
    bdai.buffer = handle();
    if (vk::GetBufferDeviceAddressKHR) {
        return vk::GetBufferDeviceAddressKHR(device(), &bdai);
    } else {
        return vk::GetBufferDeviceAddress(device(), &bdai);
    }
}

VkDeviceAddressRangeEXT Buffer::AddressRange() const {
    VkDeviceAddressRangeEXT range;
    range.address = Address();
    range.size = create_info_.size;
    return range;
}

VkStridedDeviceAddressRangeKHR Buffer::StridedAddressRange(VkDeviceSize stride) const {
    VkStridedDeviceAddressRangeKHR range;
    range.address = Address();
    range.size = create_info_.size;
    range.stride = stride;
    return range;
}

NON_DISPATCHABLE_HANDLE_DTOR(BufferView, vk::DestroyBufferView)

void BufferView::Init(const Device& dev, const VkBufferViewCreateInfo& info) {
    NON_DISPATCHABLE_HANDLE_INIT(vk::CreateBufferView, dev, &info);
}

NON_DISPATCHABLE_HANDLE_DTOR(Tensor, vk::DestroyTensorARM)

Tensor::Tensor() {
    dimensions_ = std::vector<int64_t>{1, 8, 8, 8};
    description_ = vku::InitStructHelper();
    description_.tiling = VK_TENSOR_TILING_LINEAR_ARM;
    description_.format = VK_FORMAT_R32_SINT;
    description_.dimensionCount = dimensions_.size();
    description_.pDimensions = dimensions_.data();
    description_.pStrides = nullptr;
    description_.usage = VK_TENSOR_USAGE_SHADER_BIT_ARM;

    create_info_ = vku::InitStructHelper();
    create_info_.flags = 0;
    create_info_.pDescription = &description_;
    create_info_.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
    create_info_.queueFamilyIndexCount = 0;
    create_info_.pQueueFamilyIndices = nullptr;
}

Tensor::Tensor(const Device& dev, const bool is_copy_tensor) {
    dimensions_ = std::vector<int64_t>{1, 8, 8, 8};
    description_ = vku::InitStructHelper();
    description_.tiling = VK_TENSOR_TILING_LINEAR_ARM;
    description_.format = VK_FORMAT_R32_SINT;
    description_.dimensionCount = dimensions_.size();
    description_.pDimensions = dimensions_.data();
    description_.pStrides = nullptr;
    description_.usage = VK_TENSOR_USAGE_SHADER_BIT_ARM;

    if (is_copy_tensor) {
        description_.usage |= VK_TENSOR_USAGE_TRANSFER_SRC_BIT_ARM | VK_TENSOR_USAGE_TRANSFER_DST_BIT_ARM;
    }

    create_info_ = vku::InitStructHelper();
    create_info_.flags = 0;
    create_info_.pDescription = &description_;
    create_info_.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
    create_info_.queueFamilyIndexCount = 0;
    create_info_.pQueueFamilyIndices = nullptr;

    InitNoMem(dev, create_info_);
}

Tensor::Tensor(const Device& dev, const VkTensorDescriptionARM& desc) : Tensor() {
    description_ = desc;
    create_info_.pDescription = &description_;
    InitNoMem(dev, create_info_);
}

Tensor::Tensor(const Device& dev, const VkTensorCreateInfoARM& info) {
    description_ = *info.pDescription;
    InitNoMem(dev, info);
}

void Tensor::BindToMem(VkFlags required_flags, VkFlags forbidden_flags) {
    VkMemoryRequirements2 mem_reqs = this->GetMemoryReqs();

    VkMemoryAllocateInfo tensor_alloc_info = vku::InitStructHelper();
    tensor_alloc_info.allocationSize = mem_reqs.memoryRequirements.size;
    device_->Physical().SetMemoryType(mem_reqs.memoryRequirements.memoryTypeBits, &tensor_alloc_info, required_flags,
                                      forbidden_flags);
    memory_ = vkt::DeviceMemory(*device_, tensor_alloc_info);
    VkBindTensorMemoryInfoARM bind_info = vku::InitStructHelper();
    bind_info.tensor = *this;
    bind_info.memory = memory_;
    vk::BindTensorMemoryARM(*device_, 1, &bind_info);
}

void Tensor::InitNoMem(const Device& dev, const VkTensorCreateInfoARM& info) {
    device_ = &dev;
    create_info_ = info;
    description_ = *info.pDescription;
    NON_DISPATCHABLE_HANDLE_INIT(vk::CreateTensorARM, dev, &create_info_);
}

const VkMemoryRequirements2& Tensor::GetMemoryReqs() {
    mem_req_info_ = vku::InitStructHelper();
    mem_req_info_.tensor = *this;
    mem_reqs_ = vku::InitStructHelper();
    vk::GetTensorMemoryRequirementsARM(*device_, &mem_req_info_, &mem_reqs_);
    return mem_reqs_;
}

NON_DISPATCHABLE_HANDLE_DTOR(TensorView, vk::DestroyTensorViewARM)
TensorView::TensorView(const Device& dev, const VkTensorViewCreateInfoARM& info) { Init(dev, info); }

void TensorView::Init(const Device& dev, const VkTensorViewCreateInfoARM& info) {
    device_ = &dev;
    create_info_ = info;
    NON_DISPATCHABLE_HANDLE_INIT(vk::CreateTensorViewARM, dev, &create_info_);
}

NON_DISPATCHABLE_HANDLE_DTOR(DataGraphPipelineSession, vk::DestroyDataGraphPipelineSessionARM)
DataGraphPipelineSession::DataGraphPipelineSession(const Device& dev, const VkDataGraphPipelineSessionCreateInfoARM& info) {
    create_info_ = info;
    Init(dev);
}
void DataGraphPipelineSession::Init(const Device& dev) {
    device_ = &dev;
    NON_DISPATCHABLE_HANDLE_INIT(vk::CreateDataGraphPipelineSessionARM, dev, &create_info_);
}

void DataGraphPipelineSession::GetMemoryReqs() {
    VkDataGraphPipelineSessionBindPointRequirementsInfoARM bind_info = vku::InitStructHelper();
    bind_info.session = handle();
    uint32_t count = 0;
    vk::GetDataGraphPipelineSessionBindPointRequirementsARM(*device_, &bind_info, &count, nullptr);
    bind_point_reqs_.resize(count, vku::InitStructHelper());
    vk::GetDataGraphPipelineSessionBindPointRequirementsARM(*device_, &bind_info, &count, bind_point_reqs_.data());

    mem_reqs_.resize(count);
    for (uint32_t i = 0; i < count; i++) {
        if (bind_point_reqs_[i].bindPointType != VK_DATA_GRAPH_PIPELINE_SESSION_BIND_POINT_TYPE_MEMORY_ARM) {
            continue;
        }
        VkDataGraphPipelineSessionMemoryRequirementsInfoARM session_mem_reqs = vku::InitStructHelper();
        session_mem_reqs.session = handle();
        session_mem_reqs.bindPoint = bind_point_reqs_[i].bindPoint;
        mem_reqs_[i] = vku::InitStructHelper();
        vk::GetDataGraphPipelineSessionMemoryRequirementsARM(*device_, &session_mem_reqs, &mem_reqs_[i]);
    }
}

void DataGraphPipelineSession::AllocSessionMem(std::vector<vkt::DeviceMemory>& device_mem, bool is_protected, size_t scale_factor,
                                               int32_t size_modifier) {
    assert(mem_reqs_.size() == device_mem.size());
    for (size_t i = 0; i < device_mem.size(); i++) {
        auto& mem_req = mem_reqs_[i].memoryRequirements;
        VkMemoryAllocateInfo session_alloc_info = vku::InitStructHelper();
        session_alloc_info.allocationSize = mem_req.size * scale_factor + size_modifier;
        auto flags = is_protected ? VK_MEMORY_PROPERTY_PROTECTED_BIT : 0;
        device_->Physical().SetMemoryType(mem_req.memoryTypeBits, &session_alloc_info, flags);
        device_mem[i] = vkt::DeviceMemory(*device_, session_alloc_info);
    }
}

NON_DISPATCHABLE_HANDLE_DTOR(Image, vk::DestroyImage)

Image::Image(const Device& dev, const VkImageCreateInfo& info, VkMemoryPropertyFlags mem_props, void* alloc_info_pnext)
    : device_(&dev) {
    Init(dev, info, mem_props, alloc_info_pnext);
}

Image::Image(const Device& dev, uint32_t width, uint32_t height, VkFormat format, VkImageUsageFlags usage) : device_(&dev) {
    Init(dev, width, height, 1, format, usage);
}

Image::Image(const Device& dev, const VkImageCreateInfo& info, NoMemT) : device_(&dev) { InitNoMemory(dev, info); }

Image::Image(const Device& dev, const VkImageCreateInfo& info, SetLayoutT) : device_(&dev) {
    Init(*device_, info);

    VkImageLayout newLayout;
    const auto usage = info.usage;
    if (usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
        newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
    } else if (usage & VK_IMAGE_USAGE_SAMPLED_BIT) {
        newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
    } else {
        newLayout = VK_IMAGE_LAYOUT_GENERAL;
    }

    SetLayout(newLayout);
}

Image::Image(Image&& rhs) noexcept : NonDispHandle(std::move(rhs)) {
    device_ = std::move(rhs.device_);
    rhs.device_ = nullptr;

    create_info_ = std::move(rhs.create_info_);
    rhs.create_info_ = vku::InitStructHelper();

    internal_mem_ = std::move(rhs.internal_mem_);
}

Image& Image::operator=(Image&& rhs) noexcept {
    if (&rhs == this) {
        return *this;
    }
    Destroy();
    internal_mem_.Destroy();
    NonDispHandle::operator=(std::move(rhs));

    device_ = std::move(rhs.device_);
    rhs.device_ = nullptr;

    create_info_ = std::move(rhs.create_info_);
    rhs.create_info_ = vku::InitStructHelper();

    internal_mem_ = std::move(rhs.internal_mem_);
    return *this;
}

void Image::Init(const Device& dev, const VkImageCreateInfo& info, VkMemoryPropertyFlags mem_props, void* alloc_info_pnext) {
    InitNoMemory(dev, info);

    if (initialized()) {
        auto alloc_info = DeviceMemory::GetResourceAllocInfo(dev, MemoryRequirements(), mem_props, alloc_info_pnext);
        internal_mem_.Init(dev, alloc_info);
        BindMemory(internal_mem_, 0);
    }
}

void Image::Init(const Device& dev, uint32_t width, uint32_t height, uint32_t mip_levels, VkFormat format,
                 VkImageUsageFlags usage) {
    const VkImageCreateInfo info = ImageCreateInfo2D(width, height, mip_levels, 1, format, usage, VK_IMAGE_TILING_OPTIMAL);
    Init(dev, info);
}

// Currently all init call here, so can set things for all path
void Image::InitNoMemory(const Device& dev, const VkImageCreateInfo& info) {
    if (!device_) {
        device_ = &dev;
    }
    NON_DISPATCHABLE_HANDLE_INIT(vk::CreateImage, dev, &info);
    create_info_ = info;
}

bool Image::IsCompatible(const Device& dev, const VkImageUsageFlags usages, const VkFormatFeatureFlags2 features) {
    VkFormatFeatureFlags2 all_feature_flags =
        VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT |
        VK_FORMAT_FEATURE_2_STORAGE_IMAGE_ATOMIC_BIT | VK_FORMAT_FEATURE_2_UNIFORM_TEXEL_BUFFER_BIT |
        VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_2_STORAGE_TEXEL_BUFFER_ATOMIC_BIT |
        VK_FORMAT_FEATURE_2_VERTEX_BUFFER_BIT | VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT |
        VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT |
        VK_FORMAT_FEATURE_2_BLIT_SRC_BIT | VK_FORMAT_FEATURE_2_BLIT_DST_BIT | VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_LINEAR_BIT;
    if (dev.IsEnabledExtension(VK_IMG_FILTER_CUBIC_EXTENSION_NAME)) {
        all_feature_flags |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_CUBIC_BIT;
    }

    if (dev.IsEnabledExtension(VK_KHR_MAINTENANCE_1_EXTENSION_NAME)) {
        all_feature_flags |= VK_FORMAT_FEATURE_2_TRANSFER_SRC_BIT | VK_FORMAT_FEATURE_2_TRANSFER_DST_BIT;
    }

    if (dev.IsEnabledExtension(VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME)) {
        all_feature_flags |= VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_FILTER_MINMAX_BIT;
    }

    if (dev.IsEnabledExtension(VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME)) {
        all_feature_flags |= VK_FORMAT_FEATURE_2_MIDPOINT_CHROMA_SAMPLES_BIT |
                             VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_LINEAR_FILTER_BIT |
                             VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT |
                             VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT |
                             VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_FORCEABLE_BIT |
                             VK_FORMAT_FEATURE_2_DISJOINT_BIT | VK_FORMAT_FEATURE_2_COSITED_CHROMA_SAMPLES_BIT;
    }

    if (dev.IsEnabledExtension(VK_KHR_FORMAT_FEATURE_FLAGS_2_EXTENSION_NAME)) {
        all_feature_flags |= VK_FORMAT_FEATURE_2_STORAGE_READ_WITHOUT_FORMAT_BIT |
                             VK_FORMAT_FEATURE_2_STORAGE_WRITE_WITHOUT_FORMAT_BIT |
                             VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_DEPTH_COMPARISON_BIT;
    }

    if ((features & all_feature_flags) == 0) return false;  // whole format unsupported

    if ((usages & VK_IMAGE_USAGE_SAMPLED_BIT) && !(features & VK_FORMAT_FEATURE_2_SAMPLED_IMAGE_BIT)) return false;
    if ((usages & VK_IMAGE_USAGE_STORAGE_BIT) && !(features & VK_FORMAT_FEATURE_2_STORAGE_IMAGE_BIT)) return false;
    if ((usages & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) && !(features & VK_FORMAT_FEATURE_2_COLOR_ATTACHMENT_BIT)) return false;
    if ((usages & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) && !(features & VK_FORMAT_FEATURE_2_DEPTH_STENCIL_ATTACHMENT_BIT))
        return false;

    return true;
}

VkImageCreateInfo Image::ImageCreateInfo2D(uint32_t width, uint32_t height, uint32_t mip_levels, uint32_t layers, VkFormat format,
                                           VkImageUsageFlags usage, VkImageTiling requested_tiling,
                                           const vvl::span<uint32_t>& queue_families) {
    VkImageCreateInfo create_info = vku::InitStructHelper();
    create_info.imageType = VK_IMAGE_TYPE_2D;
    create_info.format = format;
    create_info.extent.width = width;
    create_info.extent.height = height;
    create_info.extent.depth = 1;
    create_info.mipLevels = mip_levels;
    create_info.arrayLayers = layers;
    create_info.samples = VK_SAMPLE_COUNT_1_BIT;
    create_info.tiling = requested_tiling;
    create_info.usage = usage;
    if (queue_families.size() > 1) {
        create_info.sharingMode = VK_SHARING_MODE_CONCURRENT;
        create_info.queueFamilyIndexCount = static_cast<uint32_t>(queue_families.size());
        create_info.pQueueFamilyIndices = queue_families.data();
    }
    create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
    return create_info;
}

VkMemoryRequirements Image::MemoryRequirements() const {
    VkMemoryRequirements reqs;

    vk::GetImageMemoryRequirements(device(), handle(), &reqs);

    return reqs;
}

void Image::AllocateAndBindMemory(const Device& dev, VkMemoryPropertyFlags mem_props, void* alloc_info_pnext) {
    assert(!internal_mem_.initialized());
    internal_mem_.Init(dev, DeviceMemory::GetResourceAllocInfo(dev, MemoryRequirements(), mem_props, alloc_info_pnext));
    BindMemory(internal_mem_, 0);
}

void Image::BindMemory(const DeviceMemory& mem, VkDeviceSize mem_offset) {
    const auto result = vk::BindImageMemory(device(), handle(), mem, mem_offset);
    // Allow successful calls and the calls that cause validation errors (but not actual Vulkan errors).
    // In the case of a validation error, it's part of the test logic how to handle it.
    ASSERT_TRUE(result == VK_SUCCESS || result == VK_ERROR_VALIDATION_FAILED_EXT);
}

VkImageAspectFlags Image::AspectMask(VkFormat format) {
    VkImageAspectFlags image_aspect;
    if (vkuFormatIsDepthAndStencil(format)) {
        image_aspect = VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_DEPTH_BIT;
    } else if (vkuFormatIsDepthOnly(format)) {
        image_aspect = VK_IMAGE_ASPECT_DEPTH_BIT;
    } else if (vkuFormatIsStencilOnly(format)) {
        image_aspect = VK_IMAGE_ASPECT_STENCIL_BIT;
    } else {  // color
        image_aspect = VK_IMAGE_ASPECT_COLOR_BIT;
    }
    return image_aspect;
}

VkImageMemoryBarrier Image::LayoutTransitionBarrier(VkImageLayout old_layout, VkImageLayout new_layout,
                                                    const VkImageSubresourceRange& range) const {
    VkImageMemoryBarrier barrier = vku::InitStructHelper();
    barrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
    barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
    barrier.oldLayout = old_layout;
    barrier.newLayout = new_layout;
    barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    barrier.image = handle();
    barrier.subresourceRange = range;
    return barrier;
}

void Image::SetLayout(CommandBuffer& cmd_buf, VkImageLayout image_layout) {
    cmd_buf.TransitionLayout(*this, create_info_.initialLayout, image_layout);
}

void Image::SetLayout(VkImageLayout image_layout) { TransitionLayout(create_info_.initialLayout, image_layout); }

void Image::TransitionLayout(VkImageLayout old_layout, VkImageLayout new_layout) {
    CommandPool pool(*device_, device_->graphics_queue_node_index_);
    CommandBuffer cmd_buf(*device_, pool);

    cmd_buf.Begin(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT);
    cmd_buf.TransitionLayout(*this, old_layout, new_layout);
    cmd_buf.End();

    auto graphics_queue = device_->QueuesWithGraphicsCapability()[0];
    graphics_queue->SubmitAndWait(cmd_buf);
}

VkImageViewCreateInfo Image::BasicViewCreatInfo(VkImageAspectFlags aspect_mask) const {
    VkImageViewCreateInfo ci = vku::InitStructHelper();
    ci.image = handle();
    ci.format = Format();
    ci.viewType = VK_IMAGE_VIEW_TYPE_2D;
    ci.components.r = VK_COMPONENT_SWIZZLE_R;
    ci.components.g = VK_COMPONENT_SWIZZLE_G;
    ci.components.b = VK_COMPONENT_SWIZZLE_B;
    ci.components.a = VK_COMPONENT_SWIZZLE_A;
    ci.subresourceRange = {aspect_mask, 0, 1, 0, 1};
    return ci;
}

ImageView Image::CreateView(VkImageAspectFlags aspect, void* pNext) const {
    VkImageViewCreateInfo ci = BasicViewCreatInfo(aspect);
    ci.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
    ci.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
    ci.pNext = pNext;
    return ImageView(*device_, ci);
}

ImageView Image::CreateView(VkImageViewType type, uint32_t baseMipLevel, uint32_t levelCount, uint32_t baseArrayLayer,
                            uint32_t layerCount, VkImageAspectFlags aspect) const {
    VkImageViewCreateInfo ci = BasicViewCreatInfo();
    ci.viewType = type;
    ci.subresourceRange = {aspect, baseMipLevel, levelCount, baseArrayLayer, layerCount};
    return ImageView(*device_, ci);
}

NON_DISPATCHABLE_HANDLE_DTOR(ImageView, vk::DestroyImageView)

void ImageView::Init(const Device& dev, const VkImageViewCreateInfo& info) {
    NON_DISPATCHABLE_HANDLE_INIT(vk::CreateImageView, dev, &info);
}

void AccelerationStructureNV::Destroy() noexcept {
    if (!initialized()) {
        return;
    }
    PFN_vkDestroyAccelerationStructureNV vkDestroyAccelerationStructureNV =
        (PFN_vkDestroyAccelerationStructureNV)vk::GetDeviceProcAddr(device(), "vkDestroyAccelerationStructureNV");
    assert(vkDestroyAccelerationStructureNV != nullptr);

    vkDestroyAccelerationStructureNV(device(), handle(), nullptr);
    handle_ = VK_NULL_HANDLE;
}
AccelerationStructureNV::~AccelerationStructureNV() noexcept { Destroy(); }

VkMemoryRequirements2 AccelerationStructureNV::MemoryRequirements() const {
    PFN_vkGetAccelerationStructureMemoryRequirementsNV vkGetAccelerationStructureMemoryRequirementsNV =
        (PFN_vkGetAccelerationStructureMemoryRequirementsNV)vk::GetDeviceProcAddr(device(),
                                                                                  "vkGetAccelerationStructureMemoryRequirementsNV");
    assert(vkGetAccelerationStructureMemoryRequirementsNV != nullptr);
    VkMemoryRequirements2 memory_requirements = vku::InitStructHelper();
    VkAccelerationStructureMemoryRequirementsInfoNV memory_requirements_info = vku::InitStructHelper();
    memory_requirements_info.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_OBJECT_NV;
    memory_requirements_info.accelerationStructure = handle();
    vkGetAccelerationStructureMemoryRequirementsNV(device(), &memory_requirements_info, &memory_requirements);
    return memory_requirements;
}

VkMemoryRequirements2 AccelerationStructureNV::BuildScratchMemoryRequirements() const {
    PFN_vkGetAccelerationStructureMemoryRequirementsNV vkGetAccelerationStructureMemoryRequirementsNV =
        (PFN_vkGetAccelerationStructureMemoryRequirementsNV)vk::GetDeviceProcAddr(device(),
                                                                                  "vkGetAccelerationStructureMemoryRequirementsNV");
    assert(vkGetAccelerationStructureMemoryRequirementsNV != nullptr);

    VkAccelerationStructureMemoryRequirementsInfoNV memory_requirements_info = vku::InitStructHelper();
    memory_requirements_info.type = VK_ACCELERATION_STRUCTURE_MEMORY_REQUIREMENTS_TYPE_BUILD_SCRATCH_NV;
    memory_requirements_info.accelerationStructure = handle();

    VkMemoryRequirements2 memory_requirements = vku::InitStructHelper();
    vkGetAccelerationStructureMemoryRequirementsNV(device(), &memory_requirements_info, &memory_requirements);
    return memory_requirements;
}

void AccelerationStructureNV::Init(const Device& dev, const VkAccelerationStructureCreateInfoNV& info, bool init_memory) {
    PFN_vkCreateAccelerationStructureNV vkCreateAccelerationStructureNV =
        (PFN_vkCreateAccelerationStructureNV)vk::GetDeviceProcAddr(dev, "vkCreateAccelerationStructureNV");
    assert(vkCreateAccelerationStructureNV != nullptr);

    NON_DISPATCHABLE_HANDLE_INIT(vkCreateAccelerationStructureNV, dev, &info);

    info_ = info.info;

    if (init_memory) {
        memory_.Init(dev, DeviceMemory::GetResourceAllocInfo(dev, MemoryRequirements().memoryRequirements,
                                                             VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT));

        PFN_vkBindAccelerationStructureMemoryNV vkBindAccelerationStructureMemoryNV =
            (PFN_vkBindAccelerationStructureMemoryNV)vk::GetDeviceProcAddr(dev, "vkBindAccelerationStructureMemoryNV");
        assert(vkBindAccelerationStructureMemoryNV != nullptr);

        VkBindAccelerationStructureMemoryInfoNV bind_info = vku::InitStructHelper();
        bind_info.accelerationStructure = handle();
        bind_info.memory = memory_;
        ASSERT_EQ(VK_SUCCESS, vkBindAccelerationStructureMemoryNV(dev, 1, &bind_info));

        PFN_vkGetAccelerationStructureHandleNV vkGetAccelerationStructureHandleNV =
            (PFN_vkGetAccelerationStructureHandleNV)vk::GetDeviceProcAddr(dev, "vkGetAccelerationStructureHandleNV");
        assert(vkGetAccelerationStructureHandleNV != nullptr);
        ASSERT_EQ(VK_SUCCESS, vkGetAccelerationStructureHandleNV(dev, handle(), sizeof(uint64_t), &opaque_handle_));
    }
}

Buffer AccelerationStructureNV::CreateScratchBuffer(const Device& device, VkBufferCreateInfo* pCreateInfo /*= nullptr*/,
                                                    bool buffer_device_address /*= false*/) const {
    VkMemoryRequirements scratch_buffer_memory_requirements = BuildScratchMemoryRequirements().memoryRequirements;
    VkBufferCreateInfo create_info = vku::InitStructHelper();
    create_info.size = scratch_buffer_memory_requirements.size;
    if (pCreateInfo) {
        create_info.usage = pCreateInfo->usage;
    } else {
        create_info.usage = VK_BUFFER_USAGE_RAY_TRACING_BIT_NV;
        if (buffer_device_address) create_info.usage |= VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
    }

    VkMemoryAllocateFlagsInfo alloc_flags = vku::InitStructHelper();
    void* pNext = nullptr;
    if (buffer_device_address) {
        alloc_flags.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT;
        pNext = &alloc_flags;
    }

    return Buffer(device, create_info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, pNext);
}

NON_DISPATCHABLE_HANDLE_DTOR(ShaderModule, vk::DestroyShaderModule)

ShaderModule& ShaderModule::operator=(ShaderModule&& rhs) noexcept {
    Destroy();
    NonDispHandle<VkShaderModule>::operator=(std::move(rhs));
    return *this;
}

void ShaderModule::Init(const Device& dev, const VkShaderModuleCreateInfo& info) {
    NON_DISPATCHABLE_HANDLE_INIT(vk::CreateShaderModule, dev, &info);
}

VkResult ShaderModule::InitTry(const Device& dev, const VkShaderModuleCreateInfo& info) {
    VkShaderModule mod;

    VkResult err = vk::CreateShaderModule(dev, &info, NULL, &mod);
    if (err == VK_SUCCESS) NonDispHandle::init(dev, mod);

    return err;
}

NON_DISPATCHABLE_HANDLE_DTOR(Shader, vk::DestroyShaderEXT)

void Shader::Init(const Device& dev, const VkShaderCreateInfoEXT& info) {
    NON_DISPATCHABLE_HANDLE_INIT(vk::CreateShadersEXT, dev, 1u, &info);
}

VkResult Shader::InitTry(const Device& dev, const VkShaderCreateInfoEXT& info) {
    VkShaderEXT mod;

    VkResult err = vk::CreateShadersEXT(dev, 1u, &info, NULL, &mod);
    if (err == VK_SUCCESS) NonDispHandle::init(dev, mod);

    return err;
}

Shader::Shader(const Device& dev, const VkShaderStageFlagBits stage, const std::vector<uint32_t>& spv,
               const VkDescriptorSetLayout* descriptorSetLayout, const VkPushConstantRange* pushConstRange) {
    VkShaderCreateInfoEXT createInfo = vku::InitStructHelper();
    createInfo.stage = stage;
    SetNextStage(createInfo, dev.GetFeatures().tessellationShader, dev.GetFeatures().geometryShader);
    createInfo.codeType = VK_SHADER_CODE_TYPE_SPIRV_EXT;
    createInfo.codeSize = spv.size() * sizeof(spv[0]);
    createInfo.pCode = spv.data();
    createInfo.pName = "main";
    if (descriptorSetLayout) {
        createInfo.setLayoutCount = 1u;
        createInfo.pSetLayouts = descriptorSetLayout;
    }
    if (pushConstRange) {
        createInfo.pushConstantRangeCount = 1u;
        createInfo.pPushConstantRanges = pushConstRange;
    }
    Init(dev, createInfo);
}

Shader::Shader(const Device& dev, const VkShaderStageFlagBits stage, const char* code,
               const VkDescriptorSetLayout* descriptorSetLayout, const VkPushConstantRange* pushConstRange) {
    spv_target_env spv_env = SPV_ENV_VULKAN_1_0;
    if (stage == VK_SHADER_STAGE_TASK_BIT_EXT || stage == VK_SHADER_STAGE_MESH_BIT_EXT || stage == VK_SHADER_STAGE_TASK_BIT_NV ||
        stage == VK_SHADER_STAGE_MESH_BIT_NV) {
        spv_env = SPV_ENV_VULKAN_1_3;
    }
    std::vector<uint32_t> spv;
    GLSLtoSPV(dev.Physical().limits_, stage, code, spv, spv_env);

    VkShaderCreateInfoEXT createInfo = vku::InitStructHelper();
    createInfo.stage = stage;
    SetNextStage(createInfo, dev.GetFeatures().tessellationShader, dev.GetFeatures().geometryShader);
    createInfo.codeType = VK_SHADER_CODE_TYPE_SPIRV_EXT;
    createInfo.codeSize = spv.size() * sizeof(spv[0]);
    createInfo.pCode = spv.data();
    createInfo.pName = "main";
    if (descriptorSetLayout) {
        createInfo.setLayoutCount = 1u;
        createInfo.pSetLayouts = descriptorSetLayout;
    }
    if (pushConstRange) {
        createInfo.pushConstantRangeCount = 1u;
        createInfo.pPushConstantRanges = pushConstRange;
    }
    Init(dev, createInfo);
}

Shader::Shader(const Device& dev, const VkShaderStageFlagBits stage, const std::vector<uint8_t>& binary,
               const VkDescriptorSetLayout* descriptorSetLayout, const VkPushConstantRange* pushConstRange) {
    VkShaderCreateInfoEXT createInfo = vku::InitStructHelper();
    createInfo.stage = stage;
    SetNextStage(createInfo, dev.GetFeatures().tessellationShader, dev.GetFeatures().geometryShader);
    createInfo.codeType = VK_SHADER_CODE_TYPE_BINARY_EXT;
    createInfo.codeSize = binary.size();
    createInfo.pCode = binary.data();
    createInfo.pName = "main";
    if (descriptorSetLayout) {
        createInfo.setLayoutCount = 1u;
        createInfo.pSetLayouts = descriptorSetLayout;
    }
    if (pushConstRange) {
        createInfo.pushConstantRangeCount = 1u;
        createInfo.pPushConstantRanges = pushConstRange;
    }
    Init(dev, createInfo);
}

NON_DISPATCHABLE_HANDLE_DTOR(PipelineCache, vk::DestroyPipelineCache)

void PipelineCache::Init(const Device& dev, const VkPipelineCacheCreateInfo& info) {
    NON_DISPATCHABLE_HANDLE_INIT(vk::CreatePipelineCache, dev, &info);
}

NON_DISPATCHABLE_HANDLE_DTOR(Pipeline, vk::DestroyPipeline)

void Pipeline::Init(const Device& dev, const VkGraphicsPipelineCreateInfo& info) {
    VkPipelineCache cache;
    VkPipelineCacheCreateInfo ci = vku::InitStructHelper();
    VkResult err = vk::CreatePipelineCache(dev, &ci, NULL, &cache);
    if (err == VK_SUCCESS) {
        NON_DISPATCHABLE_HANDLE_INIT(vk::CreateGraphicsPipelines, dev, cache, 1, &info);
        vk::DestroyPipelineCache(dev, cache, NULL);
    }
}

VkResult Pipeline::InitTry(const Device& dev, const VkGraphicsPipelineCreateInfo& info) {
    VkPipeline pipe;
    VkPipelineCache cache;
    VkPipelineCacheCreateInfo ci = vku::InitStructHelper();
    VkResult err = vk::CreatePipelineCache(dev, &ci, NULL, &cache);
    EXPECT_EQ(VK_SUCCESS, err);
    if (err == VK_SUCCESS) {
        err = vk::CreateGraphicsPipelines(dev, cache, 1, &info, NULL, &pipe);
        if (err == VK_SUCCESS) {
            NonDispHandle::init(dev, pipe);
        }
        vk::DestroyPipelineCache(dev, cache, NULL);
    }

    return err;
}

void Pipeline::Init(const Device& dev, const VkComputePipelineCreateInfo& info) {
    VkPipelineCache cache;
    VkPipelineCacheCreateInfo ci = vku::InitStructHelper();
    VkResult err = vk::CreatePipelineCache(dev, &ci, NULL, &cache);
    if (err == VK_SUCCESS) {
        NON_DISPATCHABLE_HANDLE_INIT(vk::CreateComputePipelines, dev, cache, 1, &info);
        vk::DestroyPipelineCache(dev, cache, NULL);
    }
}

void Pipeline::Init(const Device& dev, const VkRayTracingPipelineCreateInfoKHR& info) {
    NON_DISPATCHABLE_HANDLE_INIT(vk::CreateRayTracingPipelinesKHR, dev, VK_NULL_HANDLE, VK_NULL_HANDLE, 1, &info);
}

void Pipeline::InitDeferred(const Device& dev, const VkRayTracingPipelineCreateInfoKHR& info, VkDeferredOperationKHR deferred_op) {
    // ALL parameters need to survive until deferred operation is completed
    // In our case, it means both info and handle need to be kept alive
    // => cannot use NON_DISPATCHABLE_HANDLE_INIT because used handle is a temporary
    const VkResult result = vk::CreateRayTracingPipelinesKHR(dev, deferred_op, VK_NULL_HANDLE, 1, &info, nullptr, &handle());
    ASSERT_TRUE(result == VK_OPERATION_DEFERRED_KHR || result == VK_OPERATION_NOT_DEFERRED_KHR || result == VK_SUCCESS);
    NonDispHandle::SetDevice(dev);
}

void Pipeline::Init(const Device& dev, const VkDataGraphPipelineCreateInfoARM& info) {
    NON_DISPATCHABLE_HANDLE_INIT(vk::CreateDataGraphPipelinesARM, dev, VK_NULL_HANDLE, VK_NULL_HANDLE, 1, &info);
}

NON_DISPATCHABLE_HANDLE_DTOR(PipelineLayout, vk::DestroyPipelineLayout)

void PipelineLayout::Init(const Device& dev, VkPipelineLayoutCreateInfo& info,
                          const std::vector<const DescriptorSetLayout*>& layouts) {
    std::vector<VkDescriptorSetLayout> layout_handles;
    layout_handles.reserve(layouts.size());
    std::transform(layouts.begin(), layouts.end(), std::back_inserter(layout_handles),
                   [](const DescriptorSetLayout* o) { return (o) ? o->handle() : VK_NULL_HANDLE; });

    info.setLayoutCount = static_cast<uint32_t>(layout_handles.size());
    info.pSetLayouts = layout_handles.data();

    Init(dev, info);
}

void PipelineLayout::Init(const Device& dev, VkPipelineLayoutCreateInfo& info) {
    NON_DISPATCHABLE_HANDLE_INIT(vk::CreatePipelineLayout, dev, &info);
}

NON_DISPATCHABLE_HANDLE_DTOR(Sampler, vk::DestroySampler)

void Sampler::Init(const Device& dev, const VkSamplerCreateInfo& info) {
    NON_DISPATCHABLE_HANDLE_INIT(vk::CreateSampler, dev, &info);
}

NON_DISPATCHABLE_HANDLE_DTOR(DescriptorSetLayout, vk::DestroyDescriptorSetLayout)

void DescriptorSetLayout::Init(const Device& dev, const VkDescriptorSetLayoutCreateInfo& info) {
    NON_DISPATCHABLE_HANDLE_INIT(vk::CreateDescriptorSetLayout, dev, &info);
}

VkDeviceSize DescriptorSetLayout::GetDescriptorBufferSize() const {
    VkDeviceSize size = 0;
    vk::GetDescriptorSetLayoutSizeEXT(device(), handle(), &size);
    return size;
}

VkDeviceSize DescriptorSetLayout::GetDescriptorBufferBindingOffset(uint32_t binding) const {
    VkDeviceSize size = 0;
    vk::GetDescriptorSetLayoutBindingOffsetEXT(device(), handle(), binding, &size);
    return size;
}

NON_DISPATCHABLE_HANDLE_DTOR(DescriptorPool, vk::DestroyDescriptorPool)

void DescriptorPool::Init(const Device& dev, const VkDescriptorPoolCreateInfo& info) {
    dynamic_usage_ = (info.flags & VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT) != 0;
    NON_DISPATCHABLE_HANDLE_INIT(vk::CreateDescriptorPool, dev, &info);
}

void DescriptorPool::Reset() { ASSERT_EQ(VK_SUCCESS, vk::ResetDescriptorPool(device(), handle(), 0)); }

void DescriptorSet::Destroy() noexcept {
    if (!initialized()) {
        return;
    }
    // Only call vk::Free* on sets allocated from pool with usage *_DYNAMIC
    if (containing_pool_->GetDynamicUsage()) {
        VkDescriptorSet sets[1] = {handle()};
        ASSERT_EQ(VK_SUCCESS, vk::FreeDescriptorSets(device(), containing_pool_->handle(), 1, sets));
    }
    handle_ = VK_NULL_HANDLE;
}
DescriptorSet::~DescriptorSet() noexcept { Destroy(); }

void DescriptorUpdateTemplate::Init(const Device& dev, const VkDescriptorUpdateTemplateCreateInfo& info) {
    if (vk::CreateDescriptorUpdateTemplateKHR) {
        NON_DISPATCHABLE_HANDLE_INIT(vk::CreateDescriptorUpdateTemplateKHR, dev, &info);
    } else {
        NON_DISPATCHABLE_HANDLE_INIT(vk::CreateDescriptorUpdateTemplate, dev, &info);
    }
}

void DescriptorUpdateTemplate::Destroy() noexcept {
    if (!initialized()) {
        return;
    }
    if (vk::DestroyDescriptorUpdateTemplateKHR) {
        vk::DestroyDescriptorUpdateTemplateKHR(device(), handle(), nullptr);
    } else {
        vk::DestroyDescriptorUpdateTemplate(device(), handle(), nullptr);
    }
    handle_ = VK_NULL_HANDLE;
    internal::NonDispHandle<decltype(handle_)>::Destroy();
}

DescriptorUpdateTemplate::~DescriptorUpdateTemplate() noexcept { Destroy(); }

NON_DISPATCHABLE_HANDLE_DTOR(CommandPool, vk::DestroyCommandPool)

void CommandPool::Init(const Device& dev, const VkCommandPoolCreateInfo& info) {
    NON_DISPATCHABLE_HANDLE_INIT(vk::CreateCommandPool, dev, &info);
}

void CommandPool::Init(const Device& dev, uint32_t queue_family_index, VkCommandPoolCreateFlags flags) {
    VkCommandPoolCreateInfo pool_ci = vku::InitStructHelper();
    pool_ci.flags = flags;
    pool_ci.queueFamilyIndex = queue_family_index;
    Init(dev, pool_ci);
}

CommandPool::CommandPool(const Device& dev, uint32_t queue_family_index, VkCommandPoolCreateFlags flags) {
    Init(dev, queue_family_index, flags);
}

void CommandBuffer::Destroy() noexcept {
    if (!initialized()) {
        return;
    }
    VkCommandBuffer cmds[] = {handle()};
    vk::FreeCommandBuffers(dev_handle_, cmd_pool_, 1, cmds);
    handle_ = VK_NULL_HANDLE;
}
CommandBuffer::~CommandBuffer() noexcept { Destroy(); }

CommandPool& CommandPool::operator=(CommandPool&& rhs) noexcept {
    Destroy();
    NonDispHandle<VkCommandPool>::operator=(std::move(rhs));
    return *this;
}

CommandBuffer::CommandBuffer(CommandBuffer&& rhs) noexcept : Handle(std::move(rhs)) {
    dev_handle_ = rhs.dev_handle_;
    cmd_pool_ = rhs.cmd_pool_;
    rhs.dev_handle_ = VK_NULL_HANDLE;
    rhs.cmd_pool_ = VK_NULL_HANDLE;
}

CommandBuffer& CommandBuffer::operator=(CommandBuffer&& rhs) noexcept {
    Destroy();
    dev_handle_ = rhs.dev_handle_;
    cmd_pool_ = rhs.cmd_pool_;
    handle_ = rhs.handle_;
    rhs.dev_handle_ = VK_NULL_HANDLE;
    rhs.cmd_pool_ = VK_NULL_HANDLE;
    rhs.handle_ = VK_NULL_HANDLE;
    return *this;
}

void CommandBuffer::Init(const Device& dev, const VkCommandBufferAllocateInfo& info) {
    VkCommandBuffer cmd;

    // Make sure commandPool is set
    assert(info.commandPool);

    ASSERT_EQ(VK_SUCCESS, vk::AllocateCommandBuffers(dev, &info, &cmd));
    Handle::init(cmd);
    dev_handle_ = dev;
    cmd_pool_ = info.commandPool;
}

void CommandBuffer::Init(const Device& dev, const CommandPool& pool, VkCommandBufferLevel level) {
    auto create_info = CommandBuffer::CreateInfo(pool);
    create_info.level = level;
    Init(dev, create_info);
}

void CommandBuffer::Begin(const VkCommandBufferBeginInfo* info) { ASSERT_EQ(VK_SUCCESS, vk::BeginCommandBuffer(handle(), info)); }

void CommandBuffer::Begin(VkCommandBufferUsageFlags flags) {
    VkCommandBufferBeginInfo info = vku::InitStructHelper();
    VkCommandBufferInheritanceInfo hinfo = vku::InitStructHelper();
    info.flags = flags;
    info.pInheritanceInfo = &hinfo;
    hinfo.renderPass = VK_NULL_HANDLE;
    hinfo.subpass = 0;
    hinfo.framebuffer = VK_NULL_HANDLE;
    hinfo.occlusionQueryEnable = VK_FALSE;
    hinfo.queryFlags = 0;
    hinfo.pipelineStatistics = 0;

    Begin(&info);
}

void CommandBuffer::End() {
    VkResult result = vk::EndCommandBuffer(handle());
    if (result == VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR) {
        GTEST_MESSAGE_AT_(__FILE__, __LINE__, "", ::testing::TestPartResult::kSkip)
            << "This test cannot be executed on an implementation that reports VK_ERROR_INVALID_VIDEO_STD_PARAMETERS_KHR in "
               "vkEndCommandBuffer()";
        throw testing::AssertionException(testing::TestPartResult(testing::TestPartResult::kSkip, __FILE__, __LINE__, ""));
    } else {
        ASSERT_EQ(VK_SUCCESS, result);
    }
}

void CommandBuffer::Reset(VkCommandBufferResetFlags flags) { ASSERT_EQ(VK_SUCCESS, vk::ResetCommandBuffer(handle(), flags)); }

VkCommandBufferAllocateInfo CommandBuffer::CreateInfo(VkCommandPool const& pool) {
    VkCommandBufferAllocateInfo info = vku::InitStructHelper();
    info.commandPool = pool;
    info.commandBufferCount = 1;
    return info;
}

void CommandBuffer::BeginRenderPass(const VkRenderPassBeginInfo& info, VkSubpassContents contents) {
    vk::CmdBeginRenderPass(handle(), &info, contents);
}

void CommandBuffer::BeginRenderPass(VkRenderPass rp, VkFramebuffer fb, uint32_t render_area_width, uint32_t render_area_height,
                                    uint32_t clear_count, const VkClearValue* clear_values) {
    VkRenderPassBeginInfo render_pass_begin_info = vku::InitStructHelper();
    render_pass_begin_info.renderPass = rp;
    render_pass_begin_info.framebuffer = fb;
    render_pass_begin_info.renderArea.extent.width = render_area_width;
    render_pass_begin_info.renderArea.extent.height = render_area_height;
    render_pass_begin_info.clearValueCount = clear_count;
    render_pass_begin_info.pClearValues = clear_values;
    vk::CmdBeginRenderPass(handle(), &render_pass_begin_info, VK_SUBPASS_CONTENTS_INLINE);
}

void CommandBuffer::NextSubpass(VkSubpassContents contents) { vk::CmdNextSubpass(handle(), contents); }

void CommandBuffer::EndRenderPass() { vk::CmdEndRenderPass(handle()); }

void CommandBuffer::BeginRendering(const VkRenderingInfo& renderingInfo) {
    if (vk::CmdBeginRenderingKHR) {
        vk::CmdBeginRenderingKHR(handle(), &renderingInfo);
    } else {
        vk::CmdBeginRendering(handle(), &renderingInfo);
    }
}

void CommandBuffer::BeginRenderingColor(const VkImageView imageView, VkRect2D render_area) {
    VkRenderingAttachmentInfo color_attachment = vku::InitStructHelper();
    color_attachment.imageView = imageView;
    color_attachment.imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;

    VkRenderingInfo renderingInfo = vku::InitStructHelper();
    renderingInfo.colorAttachmentCount = 1;
    renderingInfo.pColorAttachments = &color_attachment;
    renderingInfo.layerCount = 1;
    renderingInfo.renderArea = render_area;

    BeginRendering(renderingInfo);
}

void CommandBuffer::EndRendering() {
    if (vk::CmdEndRenderingKHR) {
        vk::CmdEndRenderingKHR(handle());
    } else {
        vk::CmdEndRendering(handle());
    }
}

void CommandBuffer::BindShaders(const vkt::Shader& vert_shader, const vkt::Shader& frag_shader) {
    const VkShaderStageFlagBits stages[] = {VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_FRAGMENT_BIT};
    vk::CmdBindShadersEXT(handle(), 1u, &stages[0], &vert_shader.handle());
    vk::CmdBindShadersEXT(handle(), 1u, &stages[1], &frag_shader.handle());
}

void CommandBuffer::BindShaders(const vkt::Shader& vert_shader, const vkt::Shader& geom_shader, const vkt::Shader& frag_shader) {
    const VkShaderStageFlagBits stages[] = {VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_GEOMETRY_BIT, VK_SHADER_STAGE_FRAGMENT_BIT};
    vk::CmdBindShadersEXT(handle(), 1u, &stages[0], &vert_shader.handle());
    vk::CmdBindShadersEXT(handle(), 1u, &stages[1], &geom_shader.handle());
    vk::CmdBindShadersEXT(handle(), 1u, &stages[2], &frag_shader.handle());
}

void CommandBuffer::BindShaders(const vkt::Shader& vert_shader, const vkt::Shader& tesc_shader, const vkt::Shader& tese_shader,
                                const vkt::Shader& frag_shader) {
    const VkShaderStageFlagBits stages[] = {VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
                                            VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, VK_SHADER_STAGE_FRAGMENT_BIT};
    vk::CmdBindShadersEXT(handle(), 1u, &stages[0], &vert_shader.handle());
    vk::CmdBindShadersEXT(handle(), 1u, &stages[1], &tesc_shader.handle());
    vk::CmdBindShadersEXT(handle(), 1u, &stages[2], &tese_shader.handle());
    vk::CmdBindShadersEXT(handle(), 1u, &stages[3], &frag_shader.handle());
}

void CommandBuffer::BindShaders(const vkt::Shader& vert_shader, const vkt::Shader& tesc_shader, const vkt::Shader& tese_shader,
                                const vkt::Shader& geom_shader, const vkt::Shader& frag_shader) {
    const VkShaderStageFlagBits stages[] = {VK_SHADER_STAGE_VERTEX_BIT, VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT,
                                            VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT, VK_SHADER_STAGE_GEOMETRY_BIT,
                                            VK_SHADER_STAGE_FRAGMENT_BIT};
    vk::CmdBindShadersEXT(handle(), 1u, &stages[0], &vert_shader.handle());
    vk::CmdBindShadersEXT(handle(), 1u, &stages[1], &tesc_shader.handle());
    vk::CmdBindShadersEXT(handle(), 1u, &stages[2], &tese_shader.handle());
    vk::CmdBindShadersEXT(handle(), 1u, &stages[3], &geom_shader.handle());
    vk::CmdBindShadersEXT(handle(), 1u, &stages[4], &frag_shader.handle());
}

void CommandBuffer::BindCompShader(const vkt::Shader& comp_shader) {
    const VkShaderStageFlagBits stages[] = {VK_SHADER_STAGE_COMPUTE_BIT};
    const VkShaderEXT shaders[] = {comp_shader};
    vk::CmdBindShadersEXT(handle(), 1u, stages, shaders);
}

void CommandBuffer::BindMeshShaders(const vkt::Shader& mesh_shader, const vkt::Shader& frag_shader) {
    const VkShaderStageFlagBits stages[] = {VK_SHADER_STAGE_TASK_BIT_EXT, VK_SHADER_STAGE_MESH_BIT_EXT,
                                            VK_SHADER_STAGE_FRAGMENT_BIT, VK_SHADER_STAGE_VERTEX_BIT};
    const VkShaderEXT shaders[] = {VK_NULL_HANDLE, mesh_shader, frag_shader, VK_NULL_HANDLE};
    vk::CmdBindShadersEXT(handle(), 4u, stages, shaders);
}

void CommandBuffer::BindMeshShaders(const vkt::Shader& task_shader, const vkt::Shader& mesh_shader,
                                    const vkt::Shader& frag_shader) {
    const VkShaderStageFlagBits stages[] = {VK_SHADER_STAGE_TASK_BIT_EXT, VK_SHADER_STAGE_MESH_BIT_EXT,
                                            VK_SHADER_STAGE_FRAGMENT_BIT, VK_SHADER_STAGE_VERTEX_BIT};
    const VkShaderEXT shaders[] = {task_shader, mesh_shader, frag_shader, VK_NULL_HANDLE};
    vk::CmdBindShadersEXT(handle(), 4u, stages, shaders);
}

void CommandBuffer::BeginVideoCoding(const VkVideoBeginCodingInfoKHR& beginInfo) {
    vk::CmdBeginVideoCodingKHR(handle(), &beginInfo);
}

void CommandBuffer::ControlVideoCoding(const VkVideoCodingControlInfoKHR& controlInfo) {
    vk::CmdControlVideoCodingKHR(handle(), &controlInfo);
}

void CommandBuffer::DecodeVideo(const VkVideoDecodeInfoKHR& decodeInfo) { vk::CmdDecodeVideoKHR(handle(), &decodeInfo); }

void CommandBuffer::EncodeVideo(const VkVideoEncodeInfoKHR& encodeInfo) { vk::CmdEncodeVideoKHR(handle(), &encodeInfo); }

void CommandBuffer::EndVideoCoding(const VkVideoEndCodingInfoKHR& endInfo) { vk::CmdEndVideoCodingKHR(handle(), &endInfo); }

void CommandBuffer::SetEvent(Event& event, VkPipelineStageFlags src_stage_mask) {
    vk::CmdSetEvent(handle(), event, src_stage_mask);
}

void CommandBuffer::ResetEvent(Event& event, VkPipelineStageFlags src_stageMask) {
    vk::CmdResetEvent(handle(), event, src_stageMask);
}

void CommandBuffer::WaitEvent(const Event& event, VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask) {
    vk::CmdWaitEvents(handle(), 1, &event.handle(), src_stage_mask, dst_stage_mask, 0, nullptr, 0, nullptr, 0, nullptr);
}

void CommandBuffer::WaitEvent(const Event& event, VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
                              const VkMemoryBarrier& memory_barrier) {
    vk::CmdWaitEvents(handle(), 1, &event.handle(), src_stage_mask, dst_stage_mask, 1, &memory_barrier, 0, nullptr, 0, nullptr);
}

void CommandBuffer::WaitEvent(const Event& event, VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
                              const VkBufferMemoryBarrier& buffer_barrier) {
    vk::CmdWaitEvents(handle(), 1, &event.handle(), src_stage_mask, dst_stage_mask, 0, nullptr, 1, &buffer_barrier, 0, nullptr);
}

void CommandBuffer::WaitEvent(const Event& event, VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
                              const VkImageMemoryBarrier& image_barrier) {
    vk::CmdWaitEvents(handle(), 1, &event.handle(), src_stage_mask, dst_stage_mask, 0, nullptr, 0, nullptr, 1, &image_barrier);
}

void CommandBuffer::Copy(const Buffer& src, const Buffer& dst) {
    assert(src.CreateInfo().size == dst.CreateInfo().size);
    const VkBufferCopy region = {0, 0, src.CreateInfo().size};
    vk::CmdCopyBuffer(handle(), src, dst, 1, &region);
}

void CommandBuffer::ExecuteCommands(const CommandBuffer& secondary) { vk::CmdExecuteCommands(handle(), 1, &secondary.handle()); }

void CommandBuffer::Barrier(const VkMemoryBarrier2& barrier, VkDependencyFlags dependency_flags) {
    VkDependencyInfo dep_info = DependencyInfo(barrier, dependency_flags);
    vk::CmdPipelineBarrier2(handle(), &dep_info);
}

void CommandBuffer::Barrier(const VkBufferMemoryBarrier2& buffer_barrier, VkDependencyFlags dependency_flags) {
    VkDependencyInfo dep_info = DependencyInfo(buffer_barrier, dependency_flags);
    dep_info.dependencyFlags = dependency_flags;
    vk::CmdPipelineBarrier2(handle(), &dep_info);
}

void CommandBuffer::Barrier(const VkImageMemoryBarrier2& image_barrier, VkDependencyFlags dependency_flags) {
    VkDependencyInfo dep_info = DependencyInfo(image_barrier, dependency_flags);
    vk::CmdPipelineBarrier2(handle(), &dep_info);
}

void CommandBuffer::Barrier(const VkDependencyInfo& dep_info) { vk::CmdPipelineBarrier2(handle(), &dep_info); }

void CommandBuffer::BarrierKHR(const VkMemoryBarrier2& barrier, VkDependencyFlags dependency_flags) {
    VkDependencyInfo dep_info = DependencyInfo(barrier, dependency_flags);
    vk::CmdPipelineBarrier2KHR(handle(), &dep_info);
}

void CommandBuffer::BarrierKHR(const VkBufferMemoryBarrier2& buffer_barrier, VkDependencyFlags dependency_flags) {
    VkDependencyInfo dep_info = DependencyInfo(buffer_barrier, dependency_flags);
    vk::CmdPipelineBarrier2KHR(handle(), &dep_info);
}

void CommandBuffer::BarrierKHR(const VkImageMemoryBarrier2& image_barrier, VkDependencyFlags dependency_flags) {
    VkDependencyInfo dep_info = DependencyInfo(image_barrier, dependency_flags);
    vk::CmdPipelineBarrier2KHR(handle(), &dep_info);
}

void CommandBuffer::BarrierKHR(const VkDependencyInfo& dep_info) { vk::CmdPipelineBarrier2KHR(handle(), &dep_info); }

void CommandBuffer::Barrier(const VkImageMemoryBarrier& image_barrier, VkPipelineStageFlags src_stage_mask,
                            VkPipelineStageFlags dst_stage_mask, VkDependencyFlags dependency_flags) {
    vk::CmdPipelineBarrier(handle(), src_stage_mask, dst_stage_mask, dependency_flags, 0, nullptr, 0, nullptr, 1, &image_barrier);
}

void CommandBuffer::ImageBarrier(const vkt::Image& image, VkImageLayout current_layout) {
    const VkImageSubresourceRange subresource_range = image.SubresourceRange(image.AspectMask(image.Format()));
    VkImageMemoryBarrier barrier = vku::InitStructHelper();
    barrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
    barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
    barrier.oldLayout = current_layout;
    barrier.newLayout = current_layout;
    barrier.image = image;
    barrier.subresourceRange = subresource_range;
    vk::CmdPipelineBarrier(handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
                           VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, &barrier);
}

void CommandBuffer::TransitionLayout(const vkt::Image& image, VkImageLayout old_layout, VkImageLayout new_layout) {
    const VkImageSubresourceRange subresource_range = image.SubresourceRange(image.AspectMask(image.Format()));
    VkImageMemoryBarrier barrier = vku::InitStructHelper();
    barrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
    barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
    barrier.oldLayout = old_layout;
    barrier.newLayout = new_layout;
    barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    barrier.image = image;
    barrier.subresourceRange = subresource_range;
    vk::CmdPipelineBarrier(handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
                           VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, &barrier);
}

void CommandBuffer::TransitionLayout(const VkImage image, VkImageLayout old_layout, VkImageLayout new_layout,
                                     const VkImageSubresourceRange& subresource_range) {
    VkImageMemoryBarrier barrier = vku::InitStructHelper();
    barrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
    barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
    barrier.oldLayout = old_layout;
    barrier.newLayout = new_layout;
    barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
    barrier.image = image;
    barrier.subresourceRange = subresource_range;
    vk::CmdPipelineBarrier(handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
                           VK_DEPENDENCY_BY_REGION_BIT, 0, nullptr, 0, nullptr, 1, &barrier);
}

// For positive tests, if you run with sync val, ideally want no errors.
// Many tests need a simple quick way to sync multiple commands
void CommandBuffer::FullMemoryBarrier() {
    VkMemoryBarrier mem_barrier = vku::InitStructHelper();
    mem_barrier.srcAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
    mem_barrier.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT;
    vk::CmdPipelineBarrier(handle(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, 1, &mem_barrier, 0,
                           nullptr, 0, nullptr);
}

void RenderPass::Init(const Device& dev, const VkRenderPassCreateInfo& info) {
    NON_DISPATCHABLE_HANDLE_INIT(vk::CreateRenderPass, dev, &info);
}

void RenderPass::Init(const Device& dev, const VkRenderPassCreateInfo2& info) {
    if (vk::CreateRenderPass2KHR) {
        NON_DISPATCHABLE_HANDLE_INIT(vk::CreateRenderPass2KHR, dev, &info);
    } else {
        NON_DISPATCHABLE_HANDLE_INIT(vk::CreateRenderPass2, dev, &info);
    }
}

NON_DISPATCHABLE_HANDLE_DTOR(RenderPass, vk::DestroyRenderPass)

void Framebuffer::Init(const Device& dev, const VkFramebufferCreateInfo& info) {
    NON_DISPATCHABLE_HANDLE_INIT(vk::CreateFramebuffer, dev, &info);
}

NON_DISPATCHABLE_HANDLE_DTOR(Framebuffer, vk::DestroyFramebuffer)

void SamplerYcbcrConversion::Init(const Device& dev, const VkSamplerYcbcrConversionCreateInfo& info) {
    if (vk::CreateSamplerYcbcrConversionKHR) {
        NON_DISPATCHABLE_HANDLE_INIT(vk::CreateSamplerYcbcrConversionKHR, dev, &info);
    } else {
        NON_DISPATCHABLE_HANDLE_INIT(vk::CreateSamplerYcbcrConversion, dev, &info);
    }
}

VkSamplerYcbcrConversionInfo SamplerYcbcrConversion::ConversionInfo() {
    VkSamplerYcbcrConversionInfo ycbcr_info = vku::InitStructHelper();
    ycbcr_info.conversion = handle();
    return ycbcr_info;
}

// static
VkSamplerYcbcrConversionCreateInfo SamplerYcbcrConversion::DefaultConversionInfo(VkFormat format) {
    VkSamplerYcbcrConversionCreateInfo ycbcr_create_info = vku::InitStructHelper();
    ycbcr_create_info.format = format;
    ycbcr_create_info.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY;
    ycbcr_create_info.ycbcrRange = VK_SAMPLER_YCBCR_RANGE_ITU_FULL;
    ycbcr_create_info.components = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY,
                                    VK_COMPONENT_SWIZZLE_IDENTITY};
    ycbcr_create_info.xChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN;
    ycbcr_create_info.yChromaOffset = VK_CHROMA_LOCATION_COSITED_EVEN;
    ycbcr_create_info.chromaFilter = VK_FILTER_NEAREST;
    ycbcr_create_info.forceExplicitReconstruction = false;
    return ycbcr_create_info;
}

void SamplerYcbcrConversion::Destroy() noexcept {
    if (!initialized()) {
        return;
    }
    if (vk::DestroySamplerYcbcrConversionKHR) {
        vk::DestroySamplerYcbcrConversionKHR(device(), handle(), nullptr);
    } else {
        vk::DestroySamplerYcbcrConversion(device(), handle(), nullptr);
    }
    handle_ = VK_NULL_HANDLE;
    internal::NonDispHandle<decltype(handle_)>::Destroy();
}

SamplerYcbcrConversion::~SamplerYcbcrConversion() noexcept { Destroy(); }

NON_DISPATCHABLE_HANDLE_DTOR(Swapchain, vk::DestroySwapchainKHR)

void Swapchain::Init(const Device& dev, const VkSwapchainCreateInfoKHR& info) {
    assert(!initialized());
    VkSwapchainKHR handle = VK_NULL_HANDLE;
    auto result = vk::CreateSwapchainKHR(dev, &info, nullptr, &handle);
    // NOTE: Swapchain creation has more error codes comparing to other objects that use NON_DISPATCHABLE_HANDLE_INIT macro
    ASSERT_TRUE((result == VK_SUCCESS) || (result == VK_ERROR_VALIDATION_FAILED_EXT) || (result == VK_ERROR_OUT_OF_DEVICE_MEMORY) ||
                (result == VK_ERROR_OUT_OF_HOST_MEMORY) || (result == VK_ERROR_SURFACE_LOST_KHR) ||
                (result == VK_ERROR_DEVICE_LOST) || (result == VK_ERROR_NATIVE_WINDOW_IN_USE_KHR) ||
                (result == VK_ERROR_INITIALIZATION_FAILED));
    if (result == VK_SUCCESS) {
        NonDispHandle::init(dev, handle);
    }
}

uint32_t Swapchain::GetImageCount() const {
    uint32_t image_count = 0;
    vk::GetSwapchainImagesKHR(device(), handle(), &image_count, nullptr);
    return image_count;
}

std::vector<VkImage> Swapchain::GetImages() const {
    uint32_t image_count = GetImageCount();
    std::vector<VkImage> images(image_count);
    vk::GetSwapchainImagesKHR(device(), handle(), &image_count, images.data());
    return images;
}

std::vector<vkt::CommandBuffer> Swapchain::RecordTransitionToPresentLayout(const vkt::Device& device,
                                                                           const vkt::CommandPool& command_pool,
                                                                           VkImageLayout present_layout) const {
    const std::vector<VkImage> swapchain_images = GetImages();
    std::vector<vkt::CommandBuffer> command_buffers;
    command_buffers.reserve(swapchain_images.size());
    for (size_t i = 0; i < swapchain_images.size(); i++) {
        auto& cb = command_buffers.emplace_back(device, command_pool);
        cb.Begin();
        cb.TransitionLayout(swapchain_images[i], VK_IMAGE_LAYOUT_UNDEFINED, present_layout);
        cb.End();
    }
    return command_buffers;
}

bool Swapchain::TryTransitionToPresentLayout(const vkt::Device& device, vkt::Queue& queue, const vkt::CommandPool& command_pool,
                                             VkImageLayout present_layout) {
    const std::vector<VkImage> swapchain_images = GetImages();
    auto transition_to_present_cbs = RecordTransitionToPresentLayout(device, command_pool, present_layout);
    std::vector<bool> is_transitioned(swapchain_images.size(), false);
    vkt::Fence fence(device);

    // Iterate more times than swapchain images to have a better chance to acquire all images
    const size_t iteration_count = swapchain_images.size() * 2;

    for (size_t i = 0; i < iteration_count; i++) {
        const uint32_t image_index = AcquireNextImage(fence, kWaitTimeout);
        fence.Wait(kWaitTimeout);
        fence.Reset();
        queue.SubmitAndWait(transition_to_present_cbs[image_index]);
        queue.Present(*this, image_index, vkt::no_semaphore);
        is_transitioned[image_index] = true;
    }
    queue.Wait();
    return std::all_of(is_transitioned.begin(), is_transitioned.end(), [](bool b) { return b; });
}

uint32_t Swapchain::AcquireNextImage(const Semaphore& image_acquired, uint64_t timeout, VkResult* result) {
    uint32_t image_index = 0;
    VkResult acquire_result = vk::AcquireNextImageKHR(device(), handle(), timeout, image_acquired, VK_NULL_HANDLE, &image_index);
    if (result) {
        *result = acquire_result;
    }
    return image_index;
}

uint32_t Swapchain::AcquireNextImage(const Fence& image_acquired, uint64_t timeout, VkResult* result) {
    uint32_t image_index = 0;
    VkResult acquire_result = vk::AcquireNextImageKHR(device(), handle(), timeout, VK_NULL_HANDLE, image_acquired, &image_index);
    if (result) {
        *result = acquire_result;
    }
    return image_index;
}

NON_DISPATCHABLE_HANDLE_DTOR(IndirectCommandsLayout, vk::DestroyIndirectCommandsLayoutEXT)
void IndirectCommandsLayout::Init(const Device& dev, const VkIndirectCommandsLayoutCreateInfoEXT& info) {
    NON_DISPATCHABLE_HANDLE_INIT(vk::CreateIndirectCommandsLayoutEXT, dev, &info);
}

NON_DISPATCHABLE_HANDLE_DTOR(IndirectExecutionSet, vk::DestroyIndirectExecutionSetEXT)
void IndirectExecutionSet::Init(const Device& dev, const VkIndirectExecutionSetCreateInfoEXT& info) {
    NON_DISPATCHABLE_HANDLE_INIT(vk::CreateIndirectExecutionSetEXT, dev, &info);
}

IndirectExecutionSet::IndirectExecutionSet(const Device& dev, VkPipeline init_pipeline, uint32_t max_pipelines) {
    VkIndirectExecutionSetPipelineInfoEXT exe_set_pipeline_info = vku::InitStructHelper();
    exe_set_pipeline_info.initialPipeline = init_pipeline;
    exe_set_pipeline_info.maxPipelineCount = max_pipelines;

    VkIndirectExecutionSetCreateInfoEXT exe_set_ci = vku::InitStructHelper();
    exe_set_ci.type = VK_INDIRECT_EXECUTION_SET_INFO_TYPE_PIPELINES_EXT;
    exe_set_ci.info.pPipelineInfo = &exe_set_pipeline_info;
    Init(dev, exe_set_ci);
}
IndirectExecutionSet::IndirectExecutionSet(const Device& dev, const VkIndirectExecutionSetShaderInfoEXT& shader_info) {
    VkIndirectExecutionSetCreateInfoEXT exe_set_ci = vku::InitStructHelper();
    exe_set_ci.type = VK_INDIRECT_EXECUTION_SET_INFO_TYPE_SHADER_OBJECTS_EXT;
    exe_set_ci.info.pShaderInfo = &shader_info;
    Init(dev, exe_set_ci);
}

#if defined(VK_USE_PLATFORM_WIN32_KHR)
VkResult Surface::Init(VkInstance instance, const VkWin32SurfaceCreateInfoKHR& info) {
    VkResult result = vk::CreateWin32SurfaceKHR(instance, &info, nullptr, &handle_);
    instance_ = instance;
    return result;
}
#endif
#if defined(VK_USE_PLATFORM_METAL_EXT)
VkResult Surface::Init(VkInstance instance, const VkMetalSurfaceCreateInfoEXT& info) {
    VkResult result = vk::CreateMetalSurfaceEXT(instance, &info, nullptr, &handle_);
    instance_ = instance;
    return result;
}
#endif
#if defined(VK_USE_PLATFORM_ANDROID_KHR)
VkResult Surface::Init(VkInstance instance, const VkAndroidSurfaceCreateInfoKHR& info) {
    VkResult result = vk::CreateAndroidSurfaceKHR(instance, &info, nullptr, &handle_);
    instance_ = instance;
    return result;
}
#endif
#if defined(VK_USE_PLATFORM_XLIB_KHR)
VkResult Surface::Init(VkInstance instance, const VkXlibSurfaceCreateInfoKHR& info) {
    VkResult result = vk::CreateXlibSurfaceKHR(instance, &info, nullptr, &handle_);
    instance_ = instance;
    return result;
}
#endif
#if defined(VK_USE_PLATFORM_XCB_KHR)
VkResult Surface::Init(VkInstance instance, const VkXcbSurfaceCreateInfoKHR& info) {
    VkResult result = vk::CreateXcbSurfaceKHR(instance, &info, nullptr, &handle_);
    instance_ = instance;
    return result;
}
#endif
#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
VkResult Surface::Init(VkInstance instance, const VkWaylandSurfaceCreateInfoKHR& info) {
    VkResult result = vk::CreateWaylandSurfaceKHR(instance, &info, nullptr, &handle_);
    instance_ = instance;
    return result;
}
#endif

std::vector<VkPresentModeKHR> Surface::GetPresentModes(VkPhysicalDevice physical_device) const {
    uint32_t count{};
    vk::GetPhysicalDeviceSurfacePresentModesKHR(physical_device, handle_, &count, nullptr);
    std::vector<VkPresentModeKHR> present_modes(count);
    vk::GetPhysicalDeviceSurfacePresentModesKHR(physical_device, handle_, &count, present_modes.data());
    return present_modes;
}

VkSurfacePresentScalingCapabilitiesKHR Surface::GetScalingCapabilities(VkPhysicalDevice physical_device,
                                                                       VkPresentModeKHR present_mode) const {
    VkSurfacePresentModeKHR surface_present_mode = vku::InitStructHelper();
    surface_present_mode.presentMode = present_mode;
    VkPhysicalDeviceSurfaceInfo2KHR surface_info = vku::InitStructHelper(&surface_present_mode);
    surface_info.surface = handle_;

    VkSurfacePresentScalingCapabilitiesKHR scaling_caps = vku::InitStructHelper();
    VkSurfaceCapabilities2KHR surface_caps = vku::InitStructHelper(&scaling_caps);

    vk::GetPhysicalDeviceSurfaceCapabilities2KHR(physical_device, &surface_info, &surface_caps);
    return scaling_caps;
}

struct DummyAlloc {
    static VKAPI_ATTR void* VKAPI_CALL allocFunction(void*, size_t size, size_t, VkSystemAllocationScope) { return malloc(size); };
    static VKAPI_ATTR void* VKAPI_CALL realloc(void*, void*, size_t, size_t, VkSystemAllocationScope) { return nullptr; };
    static VKAPI_ATTR void VKAPI_CALL freeFunction(void*, void* pMemory) { free(pMemory); };
    static VKAPI_ATTR void VKAPI_CALL internalAlloc(void*, size_t, VkInternalAllocationType, VkSystemAllocationScope) {};
    static VKAPI_ATTR void VKAPI_CALL internalFree(void*, size_t, VkInternalAllocationType, VkSystemAllocationScope) {};
};

const VkAllocationCallbacks* DefaultAllocator() {
    static const VkAllocationCallbacks alloc = {nullptr,
                                                DummyAlloc::allocFunction,
                                                DummyAlloc::realloc,
                                                DummyAlloc::freeFunction,
                                                DummyAlloc::internalAlloc,
                                                DummyAlloc::internalFree};

    return &alloc;
}

}  // namespace vkt
