// =====================================================================================================================
//  fennec, a free and open source game engine
//  Copyright © 2025 - 2026  Medusa Slockbower
//
//  This program is free software: you can redistribute it and/or modify
//  it under the terms of the GNU General Public License as published by
//  the Free Software Foundation, either version 3 of the License, or
//  (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License
//  along with this program.  If not, see <https://www.gnu.org/licenses/>.
// =====================================================================================================================

///
/// \file fennec/renderers/vulkan/lib/physical_device_properties.h
/// \brief
///
///
/// \details
/// \author Medusa Slockbower
///
/// \copyright Copyright © 2025 Medusa Slockbower ([GPLv3](https://www.gnu.org/licenses/gpl-3.0.en.html))
///
///


#ifndef FENNEC_RENDERERS_VULKAN_LIB_PHYSICAL_DEVICE_PROPERTIES_H
#define FENNEC_RENDERERS_VULKAN_LIB_PHYSICAL_DEVICE_PROPERTIES_H

#include <volk.h>

namespace fennec::vk
{

// Device Properties ===================================================================================================


///
/// \brief Core 1.1 Properties
struct device_properties_11 : private VkPhysicalDeviceVulkan11Properties,

                              // Vulkan 1.1 Features
                              private VkPhysicalDeviceIDProperties,
                              private VkPhysicalDeviceSubgroupProperties,
                              private VkPhysicalDevicePointClippingProperties,
                              private VkPhysicalDeviceMultiviewProperties,
                              private VkPhysicalDeviceProtectedMemoryProperties,
                              private VkPhysicalDeviceMaintenance3Properties {

// Public References ---------------------------------------------------------------------------------------------------
public:

    /// \name Properties
    /// @{

    uint8_t                (*deviceUUID)[VK_UUID_SIZE];
    uint8_t                (*driverUUID)[VK_UUID_SIZE];
    uint8_t                (*deviceLUID)[VK_LUID_SIZE];
    uint32_t*                deviceNodeMask;
    VkBool32*                deviceLUIDValid;
    uint32_t*                subgroupSize;
    VkShaderStageFlags*      subgroupSupportedStages;
    VkSubgroupFeatureFlags*  subgroupSupportedOperations;
    VkBool32*                subgroupQuadOperationsInAllStages;
    VkPointClippingBehavior* pointClippingBehavior;
    uint32_t*                maxMultiviewViewCount;
    uint32_t*                maxMultiviewInstanceIndex;
    VkBool32*                protectedNoFault;
    uint32_t*                maxPerSetDescriptors;
    VkDeviceSize*            maxMemoryAllocationSize;
    VkBool32                 useCore;

    /// @}


// Methods -------------------------------------------------------------------------------------------------------------
public:

    ///
    /// \brief Default Constructor
    /// \details Version information is necessary for this structure to fill itself in properly, so the default
    ///          constructor is not allowed.
    device_properties_11() = delete;

    ///
    /// \brief Features Constructor
    /// \param core Properties structure to poll necessary information
    device_properties_11(const VkPhysicalDeviceProperties& core)
        : VkPhysicalDeviceVulkan11Properties { }
        , VkPhysicalDeviceIDProperties { }
        , VkPhysicalDeviceSubgroupProperties { }
        , VkPhysicalDevicePointClippingProperties { }
        , VkPhysicalDeviceMultiviewProperties { }
        , VkPhysicalDeviceProtectedMemoryProperties { }
        , VkPhysicalDeviceMaintenance3Properties { }
        , deviceUUID { nullptr }
        , driverUUID { nullptr }
        , deviceLUID { nullptr }
        , deviceNodeMask { nullptr }
        , deviceLUIDValid { nullptr }
        , subgroupSize { nullptr }
        , subgroupSupportedStages { nullptr }
        , subgroupSupportedOperations { nullptr }
        , subgroupQuadOperationsInAllStages { nullptr }
        , pointClippingBehavior { nullptr }
        , maxMultiviewViewCount { nullptr }
        , maxMultiviewInstanceIndex { nullptr }
        , protectedNoFault { nullptr }
        , maxPerSetDescriptors { nullptr }
        , maxMemoryAllocationSize { nullptr }
        , useCore { core.apiVersion >= VK_API_VERSION_1_1 } {

        _clear();
        _link();
    }

    ///
    /// \brief Copy Constructor
    /// \param properties The properties structure to copy
    device_properties_11(const device_properties_11& properties)
        : VkPhysicalDeviceVulkan11Properties { properties }
        , VkPhysicalDeviceIDProperties { properties }
        , VkPhysicalDeviceSubgroupProperties { properties }
        , VkPhysicalDevicePointClippingProperties { properties }
        , VkPhysicalDeviceMultiviewProperties { properties }
        , VkPhysicalDeviceProtectedMemoryProperties { properties }
        , VkPhysicalDeviceMaintenance3Properties { properties }
        , deviceUUID { nullptr }
        , driverUUID { nullptr }
        , deviceLUID { nullptr }
        , deviceNodeMask { nullptr }
        , deviceLUIDValid { nullptr }
        , subgroupSize { nullptr }
        , subgroupSupportedStages { nullptr }
        , subgroupSupportedOperations { nullptr }
        , subgroupQuadOperationsInAllStages { nullptr }
        , pointClippingBehavior { nullptr }
        , maxMultiviewViewCount { nullptr }
        , maxMultiviewInstanceIndex { nullptr }
        , protectedNoFault { nullptr }
        , maxPerSetDescriptors { nullptr }
        , maxMemoryAllocationSize { nullptr }
        , useCore { properties.useCore } {

        _link();
    }

    ///
    /// \brief Copy Assignment
    /// \param properties The properties to copy
    /// \returns A reference to \emph{this}
    device_properties_11 operator=(const device_properties_11& properties) {
        if (this == &properties) {
            return *this;
        }

        // Copy data
        VkPhysicalDeviceVulkan11Properties::operator=(properties);
        VkPhysicalDeviceIDProperties::operator=(properties);
        VkPhysicalDeviceSubgroupProperties::operator=(properties);
        VkPhysicalDevicePointClippingProperties::operator=(properties);
        VkPhysicalDeviceMultiviewProperties::operator=(properties);
        VkPhysicalDeviceProtectedMemoryProperties::operator=(properties);
        VkPhysicalDeviceMaintenance3Properties::operator=(properties);
        useCore = properties.useCore;

        _link();

        return *this;
    }

    ///
    /// \brief Chain an extension structure
    /// \param next
    void chain(void* next) {

        if (useCore) {
            VkPhysicalDeviceVulkan11Properties::pNext = next;
        } else {
            VkPhysicalDeviceMaintenance3Properties::pNext = next;
        }
    }

    ///
    /// \brief Implicit casting for chaining
    operator void*() {

        if (useCore) {
            return static_cast<VkPhysicalDeviceVulkan11Properties*>(this);
        } else {
            return static_cast<VkPhysicalDeviceIDProperties*>(this);
        }
    }


// Helpers -------------------------------------------------------------------------------------------------------------
private:

    void _clear() {

        // Clear out the struct
        fennec::memset(this, 0, sizeof(*this));

        // Set structure types
        VkPhysicalDeviceVulkan11Properties::sType        = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES;
        VkPhysicalDeviceIDProperties::sType              = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
        VkPhysicalDeviceSubgroupProperties::sType        = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
        VkPhysicalDevicePointClippingProperties::sType   = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES;
        VkPhysicalDeviceMultiviewProperties::sType       = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES;
        VkPhysicalDeviceProtectedMemoryProperties::sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES;
        VkPhysicalDeviceMaintenance3Properties::sType    = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES;
    }

    void _link() {

        // Check if we are Core 1.1 or later
        if (useCore) {

            // Link to Core structure
            deviceUUID                        = &(VkPhysicalDeviceVulkan11Properties::deviceUUID);
            driverUUID                        = &(VkPhysicalDeviceVulkan11Properties::driverUUID);
            deviceLUID                        = &(VkPhysicalDeviceVulkan11Properties::deviceLUID);
            deviceNodeMask                    = &(VkPhysicalDeviceVulkan11Properties::deviceNodeMask);
            deviceLUIDValid                   = &(VkPhysicalDeviceVulkan11Properties::deviceLUIDValid);
            subgroupSize                      = &(VkPhysicalDeviceVulkan11Properties::subgroupSize);
            subgroupSupportedStages           = &(VkPhysicalDeviceVulkan11Properties::subgroupSupportedStages);
            subgroupSupportedOperations       = &(VkPhysicalDeviceVulkan11Properties::subgroupSupportedOperations);
            subgroupQuadOperationsInAllStages = &(VkPhysicalDeviceVulkan11Properties::subgroupQuadOperationsInAllStages);
            pointClippingBehavior             = &(VkPhysicalDeviceVulkan11Properties::pointClippingBehavior);
            maxMultiviewViewCount             = &(VkPhysicalDeviceVulkan11Properties::maxMultiviewViewCount);
            maxMultiviewInstanceIndex         = &(VkPhysicalDeviceVulkan11Properties::maxMultiviewInstanceIndex);
            protectedNoFault                  = &(VkPhysicalDeviceVulkan11Properties::protectedNoFault);
            maxPerSetDescriptors              = &(VkPhysicalDeviceVulkan11Properties::maxPerSetDescriptors);
            maxMemoryAllocationSize           = &(VkPhysicalDeviceVulkan11Properties::maxMemoryAllocationSize);

            VkPhysicalDeviceVulkan11Properties::pNext = nullptr;

            return;
        }

        // Link to Extension structures
        deviceUUID                        = &(VkPhysicalDeviceIDProperties::deviceUUID);
        driverUUID                        = &(VkPhysicalDeviceIDProperties::driverUUID);
        deviceLUID                        = &(VkPhysicalDeviceIDProperties::deviceLUID);
        deviceNodeMask                    = &(VkPhysicalDeviceIDProperties::deviceNodeMask);
        deviceLUIDValid                   = &(VkPhysicalDeviceIDProperties::deviceLUIDValid);
        subgroupSize                      = &(VkPhysicalDeviceSubgroupProperties::subgroupSize);
        subgroupSupportedStages           = &(VkPhysicalDeviceSubgroupProperties::supportedStages);
        subgroupSupportedOperations       = &(VkPhysicalDeviceSubgroupProperties::supportedOperations);
        subgroupQuadOperationsInAllStages = &(VkPhysicalDeviceSubgroupProperties::quadOperationsInAllStages);
        pointClippingBehavior             = &(VkPhysicalDevicePointClippingProperties::pointClippingBehavior);
        maxMultiviewViewCount             = &(VkPhysicalDeviceMultiviewProperties::maxMultiviewViewCount);
        maxMultiviewInstanceIndex         = &(VkPhysicalDeviceMultiviewProperties::maxMultiviewInstanceIndex);
        protectedNoFault                  = &(VkPhysicalDeviceProtectedMemoryProperties::protectedNoFault);
        maxPerSetDescriptors              = &(VkPhysicalDeviceMaintenance3Properties::maxPerSetDescriptors);
        maxMemoryAllocationSize           = &(VkPhysicalDeviceMaintenance3Properties::maxMemoryAllocationSize);

        // Daisy Chain
        VkPhysicalDeviceIDProperties::pNext              = static_cast<VkPhysicalDeviceSubgroupProperties*>(this);
        VkPhysicalDeviceSubgroupProperties::pNext        = static_cast<VkPhysicalDevicePointClippingProperties*>(this);
        VkPhysicalDevicePointClippingProperties::pNext   = static_cast<VkPhysicalDeviceMultiviewProperties*>(this);
        VkPhysicalDeviceMultiviewProperties::pNext       = static_cast<VkPhysicalDeviceProtectedMemoryProperties*>(this);
        VkPhysicalDeviceProtectedMemoryProperties::pNext = static_cast<VkPhysicalDeviceMaintenance3Properties*>(this);
        VkPhysicalDeviceMaintenance3Properties::pNext    = nullptr;
    }
};

///
/// \brief Core 1.2 Properties
struct device_properties_12 : private VkPhysicalDeviceVulkan12Properties,

                              private VkPhysicalDeviceDriverProperties,
                              private VkPhysicalDeviceFloatControlsProperties,
                              private VkPhysicalDeviceDescriptorIndexingProperties,
                              private VkPhysicalDeviceDepthStencilResolveProperties,
                              private VkPhysicalDeviceSamplerFilterMinmaxProperties,
                              private VkPhysicalDeviceTimelineSemaphoreProperties {
// Public References ---------------------------------------------------------------------------------------------------
public:

    /// \name Properties
    /// @{

    VkDriverId*                        driverID;
    char                             (*driverName)[VK_MAX_DRIVER_NAME_SIZE];
    char                             (*driverInfo)[VK_MAX_DRIVER_INFO_SIZE];
    VkConformanceVersion*              conformanceVersion;
    VkShaderFloatControlsIndependence* denormBehaviorIndependence;
    VkShaderFloatControlsIndependence* roundingModeIndependence;
    VkBool32*                          shaderSignedZeroInfNanPreserveFloat16;
    VkBool32*                          shaderSignedZeroInfNanPreserveFloat32;
    VkBool32*                          shaderSignedZeroInfNanPreserveFloat64;
    VkBool32*                          shaderDenormPreserveFloat16;
    VkBool32*                          shaderDenormPreserveFloat32;
    VkBool32*                          shaderDenormPreserveFloat64;
    VkBool32*                          shaderDenormFlushToZeroFloat16;
    VkBool32*                          shaderDenormFlushToZeroFloat32;
    VkBool32*                          shaderDenormFlushToZeroFloat64;
    VkBool32*                          shaderRoundingModeRTEFloat16;
    VkBool32*                          shaderRoundingModeRTEFloat32;
    VkBool32*                          shaderRoundingModeRTEFloat64;
    VkBool32*                          shaderRoundingModeRTZFloat16;
    VkBool32*                          shaderRoundingModeRTZFloat32;
    VkBool32*                          shaderRoundingModeRTZFloat64;
    uint32_t*                          maxUpdateAfterBindDescriptorsInAllPools;
    VkBool32*                          shaderUniformBufferArrayNonUniformIndexingNative;
    VkBool32*                          shaderSampledImageArrayNonUniformIndexingNative;
    VkBool32*                          shaderStorageBufferArrayNonUniformIndexingNative;
    VkBool32*                          shaderStorageImageArrayNonUniformIndexingNative;
    VkBool32*                          shaderInputAttachmentArrayNonUniformIndexingNative;
    VkBool32*                          robustBufferAccessUpdateAfterBind;
    VkBool32*                          quadDivergentImplicitLod;
    uint32_t*                          maxPerStageDescriptorUpdateAfterBindSamplers;
    uint32_t*                          maxPerStageDescriptorUpdateAfterBindUniformBuffers;
    uint32_t*                          maxPerStageDescriptorUpdateAfterBindStorageBuffers;
    uint32_t*                          maxPerStageDescriptorUpdateAfterBindSampledImages;
    uint32_t*                          maxPerStageDescriptorUpdateAfterBindStorageImages;
    uint32_t*                          maxPerStageDescriptorUpdateAfterBindInputAttachments;
    uint32_t*                          maxPerStageUpdateAfterBindResources;
    uint32_t*                          maxDescriptorSetUpdateAfterBindSamplers;
    uint32_t*                          maxDescriptorSetUpdateAfterBindUniformBuffers;
    uint32_t*                          maxDescriptorSetUpdateAfterBindUniformBuffersDynamic;
    uint32_t*                          maxDescriptorSetUpdateAfterBindStorageBuffers;
    uint32_t*                          maxDescriptorSetUpdateAfterBindStorageBuffersDynamic;
    uint32_t*                          maxDescriptorSetUpdateAfterBindSampledImages;
    uint32_t*                          maxDescriptorSetUpdateAfterBindStorageImages;
    uint32_t*                          maxDescriptorSetUpdateAfterBindInputAttachments;
    VkResolveModeFlags*                supportedDepthResolveModes;
    VkResolveModeFlags*                supportedStencilResolveModes;
    VkBool32*                          independentResolveNone;
    VkBool32*                          independentResolve;
    VkBool32*                          filterMinmaxSingleComponentFormats;
    VkBool32*                          filterMinmaxImageComponentMapping;
    uint64_t*                          maxTimelineSemaphoreValueDifference;
    VkSampleCountFlags*                framebufferIntegerColorSampleCounts;
    VkBool32                           useCore;

    /// @}


// Method --------------------------------------------------------------------------------------------------------------
public:

    ///
    /// \brief Default Constructor
    /// \details Version information is necessary for this structure to fill itself in properly, so the default
    ///          constructor is not allowed.
    device_properties_12() = delete;


    ///
    /// \brief Features Constructor
    /// \param core Properties structure to poll necessary information
    device_properties_12(const VkPhysicalDeviceProperties& core)
        : VkPhysicalDeviceVulkan12Properties { }
        , VkPhysicalDeviceDriverProperties { }
        , VkPhysicalDeviceFloatControlsProperties { }
        , VkPhysicalDeviceDescriptorIndexingProperties { }
        , VkPhysicalDeviceDepthStencilResolveProperties { }
        , VkPhysicalDeviceSamplerFilterMinmaxProperties { }
        , VkPhysicalDeviceTimelineSemaphoreProperties { }
        , driverID { nullptr }
        , driverName { nullptr }
        , driverInfo { nullptr }
        , conformanceVersion { nullptr }
        , denormBehaviorIndependence { nullptr }
        , roundingModeIndependence { nullptr }
        , shaderSignedZeroInfNanPreserveFloat16 { nullptr }
        , shaderSignedZeroInfNanPreserveFloat32 { nullptr }
        , shaderSignedZeroInfNanPreserveFloat64 { nullptr }
        , shaderDenormPreserveFloat16 { nullptr }
        , shaderDenormPreserveFloat32 { nullptr }
        , shaderDenormPreserveFloat64 { nullptr }
        , shaderDenormFlushToZeroFloat16 { nullptr }
        , shaderDenormFlushToZeroFloat32 { nullptr }
        , shaderDenormFlushToZeroFloat64 { nullptr }
        , shaderRoundingModeRTEFloat16 { nullptr }
        , shaderRoundingModeRTEFloat32 { nullptr }
        , shaderRoundingModeRTEFloat64 { nullptr }
        , shaderRoundingModeRTZFloat16 { nullptr }
        , shaderRoundingModeRTZFloat32 { nullptr }
        , shaderRoundingModeRTZFloat64 { nullptr }
        , maxUpdateAfterBindDescriptorsInAllPools { nullptr }
        , shaderUniformBufferArrayNonUniformIndexingNative { nullptr }
        , shaderSampledImageArrayNonUniformIndexingNative { nullptr }
        , shaderStorageBufferArrayNonUniformIndexingNative { nullptr }
        , shaderStorageImageArrayNonUniformIndexingNative { nullptr }
        , shaderInputAttachmentArrayNonUniformIndexingNative { nullptr }
        , robustBufferAccessUpdateAfterBind { nullptr }
        , quadDivergentImplicitLod { nullptr }
        , maxPerStageDescriptorUpdateAfterBindSamplers { nullptr }
        , maxPerStageDescriptorUpdateAfterBindUniformBuffers { nullptr }
        , maxPerStageDescriptorUpdateAfterBindStorageBuffers { nullptr }
        , maxPerStageDescriptorUpdateAfterBindSampledImages { nullptr }
        , maxPerStageDescriptorUpdateAfterBindStorageImages { nullptr }
        , maxPerStageDescriptorUpdateAfterBindInputAttachments { nullptr }
        , maxPerStageUpdateAfterBindResources { nullptr }
        , maxDescriptorSetUpdateAfterBindSamplers { nullptr }
        , maxDescriptorSetUpdateAfterBindUniformBuffers { nullptr }
        , maxDescriptorSetUpdateAfterBindUniformBuffersDynamic { nullptr }
        , maxDescriptorSetUpdateAfterBindStorageBuffers { nullptr }
        , maxDescriptorSetUpdateAfterBindStorageBuffersDynamic { nullptr }
        , maxDescriptorSetUpdateAfterBindSampledImages { nullptr }
        , maxDescriptorSetUpdateAfterBindStorageImages { nullptr }
        , maxDescriptorSetUpdateAfterBindInputAttachments { nullptr }
        , supportedDepthResolveModes { nullptr }
        , supportedStencilResolveModes { nullptr }
        , independentResolveNone { nullptr }
        , independentResolve { nullptr }
        , filterMinmaxSingleComponentFormats { nullptr }
        , filterMinmaxImageComponentMapping { nullptr }
        , maxTimelineSemaphoreValueDifference { nullptr }
        , framebufferIntegerColorSampleCounts { nullptr }
        , useCore { core.apiVersion >= VK_API_VERSION_1_2 } {

        _clear();
        _link();
    }


    ///
    /// \brief Copy Constructor
    /// \param properties The properties structure to copy
    device_properties_12(const device_properties_12& properties)
        : VkPhysicalDeviceVulkan12Properties { properties }
        , VkPhysicalDeviceDriverProperties { properties }
        , VkPhysicalDeviceFloatControlsProperties { properties }
        , VkPhysicalDeviceDescriptorIndexingProperties { properties }
        , VkPhysicalDeviceDepthStencilResolveProperties { properties }
        , VkPhysicalDeviceSamplerFilterMinmaxProperties { properties }
        , VkPhysicalDeviceTimelineSemaphoreProperties { properties }
        , driverID { nullptr }
        , driverName { nullptr }
        , driverInfo { nullptr }
        , conformanceVersion { nullptr }
        , denormBehaviorIndependence { nullptr }
        , roundingModeIndependence { nullptr }
        , shaderSignedZeroInfNanPreserveFloat16 { nullptr }
        , shaderSignedZeroInfNanPreserveFloat32 { nullptr }
        , shaderSignedZeroInfNanPreserveFloat64 { nullptr }
        , shaderDenormPreserveFloat16 { nullptr }
        , shaderDenormPreserveFloat32 { nullptr }
        , shaderDenormPreserveFloat64 { nullptr }
        , shaderDenormFlushToZeroFloat16 { nullptr }
        , shaderDenormFlushToZeroFloat32 { nullptr }
        , shaderDenormFlushToZeroFloat64 { nullptr }
        , shaderRoundingModeRTEFloat16 { nullptr }
        , shaderRoundingModeRTEFloat32 { nullptr }
        , shaderRoundingModeRTEFloat64 { nullptr }
        , shaderRoundingModeRTZFloat16 { nullptr }
        , shaderRoundingModeRTZFloat32 { nullptr }
        , shaderRoundingModeRTZFloat64 { nullptr }
        , maxUpdateAfterBindDescriptorsInAllPools { nullptr }
        , shaderUniformBufferArrayNonUniformIndexingNative { nullptr }
        , shaderSampledImageArrayNonUniformIndexingNative { nullptr }
        , shaderStorageBufferArrayNonUniformIndexingNative { nullptr }
        , shaderStorageImageArrayNonUniformIndexingNative { nullptr }
        , shaderInputAttachmentArrayNonUniformIndexingNative { nullptr }
        , robustBufferAccessUpdateAfterBind { nullptr }
        , quadDivergentImplicitLod { nullptr }
        , maxPerStageDescriptorUpdateAfterBindSamplers { nullptr }
        , maxPerStageDescriptorUpdateAfterBindUniformBuffers { nullptr }
        , maxPerStageDescriptorUpdateAfterBindStorageBuffers { nullptr }
        , maxPerStageDescriptorUpdateAfterBindSampledImages { nullptr }
        , maxPerStageDescriptorUpdateAfterBindStorageImages { nullptr }
        , maxPerStageDescriptorUpdateAfterBindInputAttachments { nullptr }
        , maxPerStageUpdateAfterBindResources { nullptr }
        , maxDescriptorSetUpdateAfterBindSamplers { nullptr }
        , maxDescriptorSetUpdateAfterBindUniformBuffers { nullptr }
        , maxDescriptorSetUpdateAfterBindUniformBuffersDynamic { nullptr }
        , maxDescriptorSetUpdateAfterBindStorageBuffers { nullptr }
        , maxDescriptorSetUpdateAfterBindStorageBuffersDynamic { nullptr }
        , maxDescriptorSetUpdateAfterBindSampledImages { nullptr }
        , maxDescriptorSetUpdateAfterBindStorageImages { nullptr }
        , maxDescriptorSetUpdateAfterBindInputAttachments { nullptr }
        , supportedDepthResolveModes { nullptr }
        , supportedStencilResolveModes { nullptr }
        , independentResolveNone { nullptr }
        , independentResolve { nullptr }
        , filterMinmaxSingleComponentFormats { nullptr }
        , filterMinmaxImageComponentMapping { nullptr }
        , maxTimelineSemaphoreValueDifference { nullptr }
        , framebufferIntegerColorSampleCounts { nullptr }
        , useCore { properties.useCore } {

        _link();
    }


    ///
    /// \brief Copy Assignment
    /// \param properties The properties to copy
    /// \returns A reference to \emph{this}
    device_properties_12& operator=(const device_properties_12& properties) {
        if (this == &properties) {
            return *this;
        }

        VkPhysicalDeviceVulkan12Properties::operator=(properties);
        VkPhysicalDeviceDriverProperties::operator=(properties);
        VkPhysicalDeviceFloatControlsProperties::operator=(properties);
        VkPhysicalDeviceDescriptorIndexingProperties::operator=(properties);
        VkPhysicalDeviceDepthStencilResolveProperties::operator=(properties);
        VkPhysicalDeviceSamplerFilterMinmaxProperties::operator=(properties);
        VkPhysicalDeviceTimelineSemaphoreProperties::operator=(properties);
        useCore = properties.useCore;

        _link();

        return *this;
    }

    ///
    /// \brief Chain an extension structure
    /// \param next
    void chain(void* next) {

        if (useCore) {
            VkPhysicalDeviceVulkan12Properties::pNext = next;
        } else {
            VkPhysicalDeviceTimelineSemaphoreProperties::pNext = next;
        }
    }

    ///
    /// \brief Implicit casting for chaining
    operator void*() {

        if (useCore) {
            return static_cast<VkPhysicalDeviceVulkan12Properties*>(this);
        } else {
            return static_cast<VkPhysicalDeviceDriverProperties*>(this);
        }
    }


// Helpers -------------------------------------------------------------------------------------------------------------
private:

    void _clear() {

        // Clear out the structure
        fennec::memset(this, 0, sizeof(*this));

        // Set the structure types
        VkPhysicalDeviceVulkan12Properties::sType            = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES;
        VkPhysicalDeviceDriverProperties::sType              = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
        VkPhysicalDeviceFloatControlsProperties::sType       = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES;
        VkPhysicalDeviceDescriptorIndexingProperties::sType  = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES;
        VkPhysicalDeviceDepthStencilResolveProperties::sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES;
        VkPhysicalDeviceSamplerFilterMinmaxProperties::sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES;
        VkPhysicalDeviceTimelineSemaphoreProperties::sType   = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES;
    }

    void _link() {

        // Check if we are Core 1.3 or later
        if (useCore) {

            // Link to Core structure
            driverID                                             = &(VkPhysicalDeviceVulkan12Properties::driverID);
            driverName                                           = &(VkPhysicalDeviceVulkan12Properties::driverName);
            driverInfo                                           = &(VkPhysicalDeviceVulkan12Properties::driverInfo);
            conformanceVersion                                   = &(VkPhysicalDeviceVulkan12Properties::conformanceVersion);
            denormBehaviorIndependence                           = &(VkPhysicalDeviceVulkan12Properties::denormBehaviorIndependence);
            roundingModeIndependence                             = &(VkPhysicalDeviceVulkan12Properties::roundingModeIndependence);
            shaderSignedZeroInfNanPreserveFloat16                = &(VkPhysicalDeviceVulkan12Properties::shaderSignedZeroInfNanPreserveFloat16);
            shaderSignedZeroInfNanPreserveFloat32                = &(VkPhysicalDeviceVulkan12Properties::shaderSignedZeroInfNanPreserveFloat32);
            shaderSignedZeroInfNanPreserveFloat64                = &(VkPhysicalDeviceVulkan12Properties::shaderSignedZeroInfNanPreserveFloat64);
            shaderDenormPreserveFloat16                          = &(VkPhysicalDeviceVulkan12Properties::shaderDenormPreserveFloat16);
            shaderDenormPreserveFloat32                          = &(VkPhysicalDeviceVulkan12Properties::shaderDenormPreserveFloat32);
            shaderDenormPreserveFloat64                          = &(VkPhysicalDeviceVulkan12Properties::shaderDenormPreserveFloat64);
            shaderDenormFlushToZeroFloat16                       = &(VkPhysicalDeviceVulkan12Properties::shaderDenormFlushToZeroFloat16);
            shaderDenormFlushToZeroFloat32                       = &(VkPhysicalDeviceVulkan12Properties::shaderDenormFlushToZeroFloat32);
            shaderDenormFlushToZeroFloat64                       = &(VkPhysicalDeviceVulkan12Properties::shaderDenormFlushToZeroFloat64);
            shaderRoundingModeRTEFloat16                         = &(VkPhysicalDeviceVulkan12Properties::shaderRoundingModeRTEFloat16);
            shaderRoundingModeRTEFloat32                         = &(VkPhysicalDeviceVulkan12Properties::shaderRoundingModeRTEFloat32);
            shaderRoundingModeRTEFloat64                         = &(VkPhysicalDeviceVulkan12Properties::shaderRoundingModeRTEFloat64);
            shaderRoundingModeRTZFloat16                         = &(VkPhysicalDeviceVulkan12Properties::shaderRoundingModeRTZFloat16);
            shaderRoundingModeRTZFloat32                         = &(VkPhysicalDeviceVulkan12Properties::shaderRoundingModeRTZFloat32);
            shaderRoundingModeRTZFloat64                         = &(VkPhysicalDeviceVulkan12Properties::shaderRoundingModeRTZFloat64);
            maxUpdateAfterBindDescriptorsInAllPools              = &(VkPhysicalDeviceVulkan12Properties::maxUpdateAfterBindDescriptorsInAllPools);
            shaderUniformBufferArrayNonUniformIndexingNative     = &(VkPhysicalDeviceVulkan12Properties::shaderUniformBufferArrayNonUniformIndexingNative);
            shaderSampledImageArrayNonUniformIndexingNative      = &(VkPhysicalDeviceVulkan12Properties::shaderSampledImageArrayNonUniformIndexingNative);
            shaderStorageBufferArrayNonUniformIndexingNative     = &(VkPhysicalDeviceVulkan12Properties::shaderStorageBufferArrayNonUniformIndexingNative);
            shaderStorageImageArrayNonUniformIndexingNative      = &(VkPhysicalDeviceVulkan12Properties::shaderStorageImageArrayNonUniformIndexingNative);
            shaderInputAttachmentArrayNonUniformIndexingNative   = &(VkPhysicalDeviceVulkan12Properties::shaderInputAttachmentArrayNonUniformIndexingNative);
            robustBufferAccessUpdateAfterBind                    = &(VkPhysicalDeviceVulkan12Properties::robustBufferAccessUpdateAfterBind);
            quadDivergentImplicitLod                             = &(VkPhysicalDeviceVulkan12Properties::quadDivergentImplicitLod);
            maxPerStageDescriptorUpdateAfterBindSamplers         = &(VkPhysicalDeviceVulkan12Properties::maxPerStageDescriptorUpdateAfterBindSamplers);
            maxPerStageDescriptorUpdateAfterBindUniformBuffers   = &(VkPhysicalDeviceVulkan12Properties::maxPerStageDescriptorUpdateAfterBindUniformBuffers);
            maxPerStageDescriptorUpdateAfterBindStorageBuffers   = &(VkPhysicalDeviceVulkan12Properties::maxPerStageDescriptorUpdateAfterBindStorageBuffers);
            maxPerStageDescriptorUpdateAfterBindSampledImages    = &(VkPhysicalDeviceVulkan12Properties::maxPerStageDescriptorUpdateAfterBindSampledImages);
            maxPerStageDescriptorUpdateAfterBindStorageImages    = &(VkPhysicalDeviceVulkan12Properties::maxPerStageDescriptorUpdateAfterBindStorageImages);
            maxPerStageDescriptorUpdateAfterBindInputAttachments = &(VkPhysicalDeviceVulkan12Properties::maxPerStageDescriptorUpdateAfterBindInputAttachments);
            maxPerStageUpdateAfterBindResources                  = &(VkPhysicalDeviceVulkan12Properties::maxPerStageUpdateAfterBindResources);
            maxDescriptorSetUpdateAfterBindSamplers              = &(VkPhysicalDeviceVulkan12Properties::maxDescriptorSetUpdateAfterBindSamplers);
            maxDescriptorSetUpdateAfterBindUniformBuffers        = &(VkPhysicalDeviceVulkan12Properties::maxDescriptorSetUpdateAfterBindUniformBuffers);
            maxDescriptorSetUpdateAfterBindUniformBuffersDynamic = &(VkPhysicalDeviceVulkan12Properties::maxDescriptorSetUpdateAfterBindUniformBuffersDynamic);
            maxDescriptorSetUpdateAfterBindStorageBuffers        = &(VkPhysicalDeviceVulkan12Properties::maxDescriptorSetUpdateAfterBindStorageBuffers);
            maxDescriptorSetUpdateAfterBindStorageBuffersDynamic = &(VkPhysicalDeviceVulkan12Properties::maxDescriptorSetUpdateAfterBindStorageBuffersDynamic);
            maxDescriptorSetUpdateAfterBindSampledImages         = &(VkPhysicalDeviceVulkan12Properties::maxDescriptorSetUpdateAfterBindSampledImages);
            maxDescriptorSetUpdateAfterBindStorageImages         = &(VkPhysicalDeviceVulkan12Properties::maxDescriptorSetUpdateAfterBindStorageImages);
            maxDescriptorSetUpdateAfterBindInputAttachments      = &(VkPhysicalDeviceVulkan12Properties::maxDescriptorSetUpdateAfterBindInputAttachments);
            supportedDepthResolveModes                           = &(VkPhysicalDeviceVulkan12Properties::supportedDepthResolveModes);
            supportedStencilResolveModes                         = &(VkPhysicalDeviceVulkan12Properties::supportedStencilResolveModes);
            independentResolveNone                               = &(VkPhysicalDeviceVulkan12Properties::independentResolveNone);
            independentResolve                                   = &(VkPhysicalDeviceVulkan12Properties::independentResolve);
            filterMinmaxSingleComponentFormats                   = &(VkPhysicalDeviceVulkan12Properties::filterMinmaxSingleComponentFormats);
            filterMinmaxImageComponentMapping                    = &(VkPhysicalDeviceVulkan12Properties::filterMinmaxImageComponentMapping);
            maxTimelineSemaphoreValueDifference                  = &(VkPhysicalDeviceVulkan12Properties::maxTimelineSemaphoreValueDifference);
            framebufferIntegerColorSampleCounts                  = &(VkPhysicalDeviceVulkan12Properties::framebufferIntegerColorSampleCounts);

            VkPhysicalDeviceVulkan12Properties::pNext = nullptr;

            return;
        }

        // Link to Extension structures
        driverID                                             = &(VkPhysicalDeviceDriverProperties::driverID);
        driverName                                           = &(VkPhysicalDeviceDriverProperties::driverName);
        driverInfo                                           = &(VkPhysicalDeviceDriverProperties::driverInfo);
        conformanceVersion                                   = &(VkPhysicalDeviceDriverProperties::conformanceVersion);
        denormBehaviorIndependence                           = &(VkPhysicalDeviceFloatControlsProperties::denormBehaviorIndependence);
        roundingModeIndependence                             = &(VkPhysicalDeviceFloatControlsProperties::roundingModeIndependence);
        shaderSignedZeroInfNanPreserveFloat16                = &(VkPhysicalDeviceFloatControlsProperties::shaderSignedZeroInfNanPreserveFloat16);
        shaderSignedZeroInfNanPreserveFloat32                = &(VkPhysicalDeviceFloatControlsProperties::shaderSignedZeroInfNanPreserveFloat32);
        shaderSignedZeroInfNanPreserveFloat64                = &(VkPhysicalDeviceFloatControlsProperties::shaderSignedZeroInfNanPreserveFloat64);
        shaderDenormPreserveFloat16                          = &(VkPhysicalDeviceFloatControlsProperties::shaderDenormPreserveFloat16);
        shaderDenormPreserveFloat32                          = &(VkPhysicalDeviceFloatControlsProperties::shaderDenormPreserveFloat32);
        shaderDenormPreserveFloat64                          = &(VkPhysicalDeviceFloatControlsProperties::shaderDenormPreserveFloat64);
        shaderDenormFlushToZeroFloat16                       = &(VkPhysicalDeviceFloatControlsProperties::shaderDenormFlushToZeroFloat16);
        shaderDenormFlushToZeroFloat32                       = &(VkPhysicalDeviceFloatControlsProperties::shaderDenormFlushToZeroFloat32);
        shaderDenormFlushToZeroFloat64                       = &(VkPhysicalDeviceFloatControlsProperties::shaderDenormFlushToZeroFloat64);
        shaderRoundingModeRTEFloat16                         = &(VkPhysicalDeviceFloatControlsProperties::shaderRoundingModeRTEFloat16);
        shaderRoundingModeRTEFloat32                         = &(VkPhysicalDeviceFloatControlsProperties::shaderRoundingModeRTEFloat32);
        shaderRoundingModeRTEFloat64                         = &(VkPhysicalDeviceFloatControlsProperties::shaderRoundingModeRTEFloat64);
        shaderRoundingModeRTZFloat16                         = &(VkPhysicalDeviceFloatControlsProperties::shaderRoundingModeRTZFloat16);
        shaderRoundingModeRTZFloat32                         = &(VkPhysicalDeviceFloatControlsProperties::shaderRoundingModeRTZFloat32);
        shaderRoundingModeRTZFloat64                         = &(VkPhysicalDeviceFloatControlsProperties::shaderRoundingModeRTZFloat64);
        maxUpdateAfterBindDescriptorsInAllPools              = &(VkPhysicalDeviceDescriptorIndexingProperties::maxUpdateAfterBindDescriptorsInAllPools);
        shaderUniformBufferArrayNonUniformIndexingNative     = &(VkPhysicalDeviceDescriptorIndexingProperties::shaderUniformBufferArrayNonUniformIndexingNative);
        shaderSampledImageArrayNonUniformIndexingNative      = &(VkPhysicalDeviceDescriptorIndexingProperties::shaderSampledImageArrayNonUniformIndexingNative);
        shaderStorageBufferArrayNonUniformIndexingNative     = &(VkPhysicalDeviceDescriptorIndexingProperties::shaderStorageBufferArrayNonUniformIndexingNative);
        shaderStorageImageArrayNonUniformIndexingNative      = &(VkPhysicalDeviceDescriptorIndexingProperties::shaderStorageImageArrayNonUniformIndexingNative);
        shaderInputAttachmentArrayNonUniformIndexingNative   = &(VkPhysicalDeviceDescriptorIndexingProperties::shaderInputAttachmentArrayNonUniformIndexingNative);
        robustBufferAccessUpdateAfterBind                    = &(VkPhysicalDeviceDescriptorIndexingProperties::robustBufferAccessUpdateAfterBind);
        quadDivergentImplicitLod                             = &(VkPhysicalDeviceDescriptorIndexingProperties::quadDivergentImplicitLod);
        maxPerStageDescriptorUpdateAfterBindSamplers         = &(VkPhysicalDeviceDescriptorIndexingProperties::maxPerStageDescriptorUpdateAfterBindSamplers);
        maxPerStageDescriptorUpdateAfterBindUniformBuffers   = &(VkPhysicalDeviceDescriptorIndexingProperties::maxPerStageDescriptorUpdateAfterBindUniformBuffers);
        maxPerStageDescriptorUpdateAfterBindStorageBuffers   = &(VkPhysicalDeviceDescriptorIndexingProperties::maxPerStageDescriptorUpdateAfterBindStorageBuffers);
        maxPerStageDescriptorUpdateAfterBindSampledImages    = &(VkPhysicalDeviceDescriptorIndexingProperties::maxPerStageDescriptorUpdateAfterBindSampledImages);
        maxPerStageDescriptorUpdateAfterBindStorageImages    = &(VkPhysicalDeviceDescriptorIndexingProperties::maxPerStageDescriptorUpdateAfterBindStorageImages);
        maxPerStageDescriptorUpdateAfterBindInputAttachments = &(VkPhysicalDeviceDescriptorIndexingProperties::maxPerStageDescriptorUpdateAfterBindInputAttachments);
        maxPerStageUpdateAfterBindResources                  = &(VkPhysicalDeviceDescriptorIndexingProperties::maxPerStageUpdateAfterBindResources);
        maxDescriptorSetUpdateAfterBindSamplers              = &(VkPhysicalDeviceDescriptorIndexingProperties::maxDescriptorSetUpdateAfterBindSamplers);
        maxDescriptorSetUpdateAfterBindUniformBuffers        = &(VkPhysicalDeviceDescriptorIndexingProperties::maxDescriptorSetUpdateAfterBindUniformBuffers);
        maxDescriptorSetUpdateAfterBindUniformBuffersDynamic = &(VkPhysicalDeviceDescriptorIndexingProperties::maxDescriptorSetUpdateAfterBindUniformBuffersDynamic);
        maxDescriptorSetUpdateAfterBindStorageBuffers        = &(VkPhysicalDeviceDescriptorIndexingProperties::maxDescriptorSetUpdateAfterBindStorageBuffers);
        maxDescriptorSetUpdateAfterBindStorageBuffersDynamic = &(VkPhysicalDeviceDescriptorIndexingProperties::maxDescriptorSetUpdateAfterBindStorageBuffersDynamic);
        maxDescriptorSetUpdateAfterBindSampledImages         = &(VkPhysicalDeviceDescriptorIndexingProperties::maxDescriptorSetUpdateAfterBindSampledImages);
        maxDescriptorSetUpdateAfterBindStorageImages         = &(VkPhysicalDeviceDescriptorIndexingProperties::maxDescriptorSetUpdateAfterBindStorageImages);
        maxDescriptorSetUpdateAfterBindInputAttachments      = &(VkPhysicalDeviceDescriptorIndexingProperties::maxDescriptorSetUpdateAfterBindInputAttachments);
        supportedDepthResolveModes                           = &(VkPhysicalDeviceDepthStencilResolveProperties::supportedDepthResolveModes);
        supportedStencilResolveModes                         = &(VkPhysicalDeviceDepthStencilResolveProperties::supportedStencilResolveModes);
        independentResolveNone                               = &(VkPhysicalDeviceDepthStencilResolveProperties::independentResolveNone);
        independentResolve                                   = &(VkPhysicalDeviceDepthStencilResolveProperties::independentResolve);
        filterMinmaxSingleComponentFormats                   = &(VkPhysicalDeviceSamplerFilterMinmaxProperties::filterMinmaxSingleComponentFormats);
        filterMinmaxImageComponentMapping                    = &(VkPhysicalDeviceSamplerFilterMinmaxProperties::filterMinmaxImageComponentMapping);
        maxTimelineSemaphoreValueDifference                  = &(VkPhysicalDeviceTimelineSemaphoreProperties::maxTimelineSemaphoreValueDifference);

        // These features are only available in 1.2 Core
//      framebufferIntegerColorSampleCounts                  = &(VkPhysicalDeviceTimelineSemaphoreProperties::framebufferIntegerColorSampleCounts);

        // Daisy chain
        VkPhysicalDeviceDriverProperties::pNext              = static_cast<VkPhysicalDeviceFloatControlsProperties*>(this);
        VkPhysicalDeviceFloatControlsProperties::pNext       = static_cast<VkPhysicalDeviceDescriptorIndexingProperties*>(this);
        VkPhysicalDeviceDescriptorIndexingProperties::pNext  = static_cast<VkPhysicalDeviceDepthStencilResolveProperties*>(this);
        VkPhysicalDeviceDepthStencilResolveProperties::pNext = static_cast<VkPhysicalDeviceSamplerFilterMinmaxProperties*>(this);
        VkPhysicalDeviceSamplerFilterMinmaxProperties::pNext = static_cast<VkPhysicalDeviceTimelineSemaphoreProperties*>(this);
        VkPhysicalDeviceTimelineSemaphoreProperties::pNext   = nullptr;
    }
};

///
/// \brief Core 1.3 Properties
struct device_properties_13 : private VkPhysicalDeviceVulkan13Properties,

                              private VkPhysicalDeviceSubgroupSizeControlProperties,
                              private VkPhysicalDeviceInlineUniformBlockProperties,
                              private VkPhysicalDeviceShaderIntegerDotProductProperties,
                              private VkPhysicalDeviceTexelBufferAlignmentProperties,
                              private VkPhysicalDeviceMaintenance4Properties {

// Public References ---------------------------------------------------------------------------------------------------
public:

    /// \name Properties
    /// @{

    uint32_t*           minSubgroupSize;
    uint32_t*           maxSubgroupSize;
    uint32_t*           maxComputeWorkgroupSubgroups;
    VkShaderStageFlags* requiredSubgroupSizeStages;
    uint32_t*           maxInlineUniformBlockSize;
    uint32_t*           maxPerStageDescriptorInlineUniformBlocks;
    uint32_t*           maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks;
    uint32_t*           maxDescriptorSetInlineUniformBlocks;
    uint32_t*           maxDescriptorSetUpdateAfterBindInlineUniformBlocks;
    uint32_t*           maxInlineUniformTotalSize;
    VkBool32*           integerDotProduct8BitUnsignedAccelerated;
    VkBool32*           integerDotProduct8BitSignedAccelerated;
    VkBool32*           integerDotProduct8BitMixedSignednessAccelerated;
    VkBool32*           integerDotProduct4x8BitPackedUnsignedAccelerated;
    VkBool32*           integerDotProduct4x8BitPackedSignedAccelerated;
    VkBool32*           integerDotProduct4x8BitPackedMixedSignednessAccelerated;
    VkBool32*           integerDotProduct16BitUnsignedAccelerated;
    VkBool32*           integerDotProduct16BitSignedAccelerated;
    VkBool32*           integerDotProduct16BitMixedSignednessAccelerated;
    VkBool32*           integerDotProduct32BitUnsignedAccelerated;
    VkBool32*           integerDotProduct32BitSignedAccelerated;
    VkBool32*           integerDotProduct32BitMixedSignednessAccelerated;
    VkBool32*           integerDotProduct64BitUnsignedAccelerated;
    VkBool32*           integerDotProduct64BitSignedAccelerated;
    VkBool32*           integerDotProduct64BitMixedSignednessAccelerated;
    VkBool32*           integerDotProductAccumulatingSaturating8BitUnsignedAccelerated;
    VkBool32*           integerDotProductAccumulatingSaturating8BitSignedAccelerated;
    VkBool32*           integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated;
    VkBool32*           integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated;
    VkBool32*           integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated;
    VkBool32*           integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated;
    VkBool32*           integerDotProductAccumulatingSaturating16BitUnsignedAccelerated;
    VkBool32*           integerDotProductAccumulatingSaturating16BitSignedAccelerated;
    VkBool32*           integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerated;
    VkBool32*           integerDotProductAccumulatingSaturating32BitUnsignedAccelerated;
    VkBool32*           integerDotProductAccumulatingSaturating32BitSignedAccelerated;
    VkBool32*           integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerated;
    VkBool32*           integerDotProductAccumulatingSaturating64BitUnsignedAccelerated;
    VkBool32*           integerDotProductAccumulatingSaturating64BitSignedAccelerated;
    VkBool32*           integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerated;
    VkDeviceSize*       storageTexelBufferOffsetAlignmentBytes;
    VkBool32*           storageTexelBufferOffsetSingleTexelAlignment;
    VkDeviceSize*       uniformTexelBufferOffsetAlignmentBytes;
    VkBool32*           uniformTexelBufferOffsetSingleTexelAlignment;
    VkDeviceSize*       maxBufferSize;
    VkBool32            useCore;

    /// @}


// Methods -------------------------------------------------------------------------------------------------------------
public:

    ///
    /// \brief Default Constructor
    /// \details Version information is necessary for this structure to fill itself in properly, so the default
    ///          constructor is not allowed.
    device_properties_13() = delete;


    ///
    /// \brief Features Constructor
    /// \param core Properties structure to poll necessary information
    device_properties_13(const VkPhysicalDeviceProperties& core)
        : VkPhysicalDeviceVulkan13Properties { }
        , VkPhysicalDeviceSubgroupSizeControlProperties { }
        , VkPhysicalDeviceInlineUniformBlockProperties { }
        , VkPhysicalDeviceShaderIntegerDotProductProperties { }
        , VkPhysicalDeviceTexelBufferAlignmentProperties { }
        , VkPhysicalDeviceMaintenance4Properties { }
        , minSubgroupSize { nullptr }
        , maxSubgroupSize { nullptr }
        , maxComputeWorkgroupSubgroups { nullptr }
        , requiredSubgroupSizeStages { nullptr }
        , maxInlineUniformBlockSize { nullptr }
        , maxPerStageDescriptorInlineUniformBlocks { nullptr }
        , maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks { nullptr }
        , maxDescriptorSetInlineUniformBlocks { nullptr }
        , maxDescriptorSetUpdateAfterBindInlineUniformBlocks { nullptr }
        , maxInlineUniformTotalSize { nullptr }
        , integerDotProduct8BitUnsignedAccelerated { nullptr }
        , integerDotProduct8BitSignedAccelerated { nullptr }
        , integerDotProduct8BitMixedSignednessAccelerated { nullptr }
        , integerDotProduct4x8BitPackedUnsignedAccelerated { nullptr }
        , integerDotProduct4x8BitPackedSignedAccelerated { nullptr }
        , integerDotProduct4x8BitPackedMixedSignednessAccelerated { nullptr }
        , integerDotProduct16BitUnsignedAccelerated { nullptr }
        , integerDotProduct16BitSignedAccelerated { nullptr }
        , integerDotProduct16BitMixedSignednessAccelerated { nullptr }
        , integerDotProduct32BitUnsignedAccelerated { nullptr }
        , integerDotProduct32BitSignedAccelerated { nullptr }
        , integerDotProduct32BitMixedSignednessAccelerated { nullptr }
        , integerDotProduct64BitUnsignedAccelerated { nullptr }
        , integerDotProduct64BitSignedAccelerated { nullptr }
        , integerDotProduct64BitMixedSignednessAccelerated { nullptr }
        , integerDotProductAccumulatingSaturating8BitUnsignedAccelerated { nullptr }
        , integerDotProductAccumulatingSaturating8BitSignedAccelerated { nullptr }
        , integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated { nullptr }
        , integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated { nullptr }
        , integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated { nullptr }
        , integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated { nullptr }
        , integerDotProductAccumulatingSaturating16BitUnsignedAccelerated { nullptr }
        , integerDotProductAccumulatingSaturating16BitSignedAccelerated { nullptr }
        , integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerated { nullptr }
        , integerDotProductAccumulatingSaturating32BitUnsignedAccelerated { nullptr }
        , integerDotProductAccumulatingSaturating32BitSignedAccelerated { nullptr }
        , integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerated { nullptr }
        , integerDotProductAccumulatingSaturating64BitUnsignedAccelerated { nullptr }
        , integerDotProductAccumulatingSaturating64BitSignedAccelerated { nullptr }
        , integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerated { nullptr }
        , storageTexelBufferOffsetAlignmentBytes { nullptr }
        , storageTexelBufferOffsetSingleTexelAlignment { nullptr }
        , uniformTexelBufferOffsetAlignmentBytes { nullptr }
        , uniformTexelBufferOffsetSingleTexelAlignment { nullptr }
        , maxBufferSize { nullptr }
        , useCore { core.apiVersion >= VK_API_VERSION_1_3 } {

        _clear();
        _link();
    }


    ///
    /// \brief Copy Constructor
    /// \param properties The properties structure to copy
    device_properties_13(const device_properties_13& properties)
        : VkPhysicalDeviceVulkan13Properties { properties }
        , VkPhysicalDeviceSubgroupSizeControlProperties { properties }
        , VkPhysicalDeviceInlineUniformBlockProperties { properties }
        , VkPhysicalDeviceShaderIntegerDotProductProperties { properties }
        , VkPhysicalDeviceTexelBufferAlignmentProperties { properties }
        , VkPhysicalDeviceMaintenance4Properties { properties }
        , minSubgroupSize { nullptr }
        , maxSubgroupSize { nullptr }
        , maxComputeWorkgroupSubgroups { nullptr }
        , requiredSubgroupSizeStages { nullptr }
        , maxInlineUniformBlockSize { nullptr }
        , maxPerStageDescriptorInlineUniformBlocks { nullptr }
        , maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks { nullptr }
        , maxDescriptorSetInlineUniformBlocks { nullptr }
        , maxDescriptorSetUpdateAfterBindInlineUniformBlocks { nullptr }
        , maxInlineUniformTotalSize { nullptr }
        , integerDotProduct8BitUnsignedAccelerated { nullptr }
        , integerDotProduct8BitSignedAccelerated { nullptr }
        , integerDotProduct8BitMixedSignednessAccelerated { nullptr }
        , integerDotProduct4x8BitPackedUnsignedAccelerated { nullptr }
        , integerDotProduct4x8BitPackedSignedAccelerated { nullptr }
        , integerDotProduct4x8BitPackedMixedSignednessAccelerated { nullptr }
        , integerDotProduct16BitUnsignedAccelerated { nullptr }
        , integerDotProduct16BitSignedAccelerated { nullptr }
        , integerDotProduct16BitMixedSignednessAccelerated { nullptr }
        , integerDotProduct32BitUnsignedAccelerated { nullptr }
        , integerDotProduct32BitSignedAccelerated { nullptr }
        , integerDotProduct32BitMixedSignednessAccelerated { nullptr }
        , integerDotProduct64BitUnsignedAccelerated { nullptr }
        , integerDotProduct64BitSignedAccelerated { nullptr }
        , integerDotProduct64BitMixedSignednessAccelerated { nullptr }
        , integerDotProductAccumulatingSaturating8BitUnsignedAccelerated { nullptr }
        , integerDotProductAccumulatingSaturating8BitSignedAccelerated { nullptr }
        , integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated { nullptr }
        , integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated { nullptr }
        , integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated { nullptr }
        , integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated { nullptr }
        , integerDotProductAccumulatingSaturating16BitUnsignedAccelerated { nullptr }
        , integerDotProductAccumulatingSaturating16BitSignedAccelerated { nullptr }
        , integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerated { nullptr }
        , integerDotProductAccumulatingSaturating32BitUnsignedAccelerated { nullptr }
        , integerDotProductAccumulatingSaturating32BitSignedAccelerated { nullptr }
        , integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerated { nullptr }
        , integerDotProductAccumulatingSaturating64BitUnsignedAccelerated { nullptr }
        , integerDotProductAccumulatingSaturating64BitSignedAccelerated { nullptr }
        , integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerated { nullptr }
        , storageTexelBufferOffsetAlignmentBytes { nullptr }
        , storageTexelBufferOffsetSingleTexelAlignment { nullptr }
        , uniformTexelBufferOffsetAlignmentBytes { nullptr }
        , uniformTexelBufferOffsetSingleTexelAlignment { nullptr }
        , maxBufferSize { nullptr }
        , useCore { properties.useCore } {

        _link();
    }


    ///
    /// \brief Copy Assignment
    /// \param properties The properties structure to copy
    /// \returns A reference to \emph{this}
    device_properties_13& operator=(const device_properties_13& properties) {
        if (&properties == this) {
            return *this;
        }

        VkPhysicalDeviceVulkan13Properties::operator=(properties);
        VkPhysicalDeviceSubgroupSizeControlProperties::operator=(properties);
        VkPhysicalDeviceInlineUniformBlockProperties::operator=(properties);
        VkPhysicalDeviceShaderIntegerDotProductProperties::operator=(properties);
        VkPhysicalDeviceTexelBufferAlignmentProperties::operator=(properties);
        VkPhysicalDeviceMaintenance4Properties::operator=(properties);

        _link();

        return *this;
    }

    ///
    /// \brief Chain an extension structure
    /// \param next
    void chain(void* next) {

        if (useCore) {
            VkPhysicalDeviceVulkan13Properties::pNext = next;
        } else {
            VkPhysicalDeviceMaintenance4Properties::pNext = next;
        }
    }

    ///
    /// \brief Implicit casting for chaining
    operator void*() {

        if (useCore) {
            return static_cast<VkPhysicalDeviceVulkan13Properties*>(this);
        } else {
            return static_cast<VkPhysicalDeviceSubgroupSizeControlProperties*>(this);
        }
    }


// Helpers -------------------------------------------------------------------------------------------------------------
private:

    void _clear() {

        // Clear the structure
        fennec::memset(this, 0, sizeof(*this));

        // Set the structure types
        VkPhysicalDeviceVulkan13Properties::sType                = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_3_PROPERTIES;
        VkPhysicalDeviceSubgroupSizeControlProperties::sType     = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_SIZE_CONTROL_PROPERTIES;
        VkPhysicalDeviceInlineUniformBlockProperties::sType      = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_INLINE_UNIFORM_BLOCK_PROPERTIES;
        VkPhysicalDeviceShaderIntegerDotProductProperties::sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_INTEGER_DOT_PRODUCT_PROPERTIES;
        VkPhysicalDeviceTexelBufferAlignmentProperties::sType    = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TEXEL_BUFFER_ALIGNMENT_PROPERTIES;
        VkPhysicalDeviceMaintenance4Properties::sType            = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_PROPERTIES;
    }

    void _link() {

        if (useCore) {
            minSubgroupSize                                                               = &(VkPhysicalDeviceVulkan13Properties::minSubgroupSize);
            maxSubgroupSize                                                               = &(VkPhysicalDeviceVulkan13Properties::maxSubgroupSize);
            maxComputeWorkgroupSubgroups                                                  = &(VkPhysicalDeviceVulkan13Properties::maxComputeWorkgroupSubgroups);
            requiredSubgroupSizeStages                                                    = &(VkPhysicalDeviceVulkan13Properties::requiredSubgroupSizeStages);
            maxInlineUniformBlockSize                                                     = &(VkPhysicalDeviceVulkan13Properties::maxInlineUniformBlockSize);
            maxPerStageDescriptorInlineUniformBlocks                                      = &(VkPhysicalDeviceVulkan13Properties::maxPerStageDescriptorInlineUniformBlocks);
            maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks                       = &(VkPhysicalDeviceVulkan13Properties::maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks);
            maxDescriptorSetInlineUniformBlocks                                           = &(VkPhysicalDeviceVulkan13Properties::maxDescriptorSetInlineUniformBlocks);
            maxDescriptorSetUpdateAfterBindInlineUniformBlocks                            = &(VkPhysicalDeviceVulkan13Properties::maxDescriptorSetUpdateAfterBindInlineUniformBlocks);
            maxInlineUniformTotalSize                                                     = &(VkPhysicalDeviceVulkan13Properties::maxInlineUniformTotalSize);
            integerDotProduct8BitUnsignedAccelerated                                      = &(VkPhysicalDeviceVulkan13Properties::integerDotProduct8BitUnsignedAccelerated);
            integerDotProduct8BitSignedAccelerated                                        = &(VkPhysicalDeviceVulkan13Properties::integerDotProduct8BitSignedAccelerated);
            integerDotProduct8BitMixedSignednessAccelerated                               = &(VkPhysicalDeviceVulkan13Properties::integerDotProduct8BitMixedSignednessAccelerated);
            integerDotProduct4x8BitPackedUnsignedAccelerated                              = &(VkPhysicalDeviceVulkan13Properties::integerDotProduct4x8BitPackedUnsignedAccelerated);
            integerDotProduct4x8BitPackedSignedAccelerated                                = &(VkPhysicalDeviceVulkan13Properties::integerDotProduct4x8BitPackedSignedAccelerated);
            integerDotProduct4x8BitPackedMixedSignednessAccelerated                       = &(VkPhysicalDeviceVulkan13Properties::integerDotProduct4x8BitPackedMixedSignednessAccelerated);
            integerDotProduct16BitUnsignedAccelerated                                     = &(VkPhysicalDeviceVulkan13Properties::integerDotProduct16BitUnsignedAccelerated);
            integerDotProduct16BitSignedAccelerated                                       = &(VkPhysicalDeviceVulkan13Properties::integerDotProduct16BitSignedAccelerated);
            integerDotProduct16BitMixedSignednessAccelerated                              = &(VkPhysicalDeviceVulkan13Properties::integerDotProduct16BitMixedSignednessAccelerated);
            integerDotProduct32BitUnsignedAccelerated                                     = &(VkPhysicalDeviceVulkan13Properties::integerDotProduct32BitUnsignedAccelerated);
            integerDotProduct32BitSignedAccelerated                                       = &(VkPhysicalDeviceVulkan13Properties::integerDotProduct32BitSignedAccelerated);
            integerDotProduct32BitMixedSignednessAccelerated                              = &(VkPhysicalDeviceVulkan13Properties::integerDotProduct32BitMixedSignednessAccelerated);
            integerDotProduct64BitUnsignedAccelerated                                     = &(VkPhysicalDeviceVulkan13Properties::integerDotProduct64BitUnsignedAccelerated);
            integerDotProduct64BitSignedAccelerated                                       = &(VkPhysicalDeviceVulkan13Properties::integerDotProduct64BitSignedAccelerated);
            integerDotProduct64BitMixedSignednessAccelerated                              = &(VkPhysicalDeviceVulkan13Properties::integerDotProduct64BitMixedSignednessAccelerated);
            integerDotProductAccumulatingSaturating8BitUnsignedAccelerated                = &(VkPhysicalDeviceVulkan13Properties::integerDotProductAccumulatingSaturating8BitUnsignedAccelerated);
            integerDotProductAccumulatingSaturating8BitSignedAccelerated                  = &(VkPhysicalDeviceVulkan13Properties::integerDotProductAccumulatingSaturating8BitSignedAccelerated);
            integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated         = &(VkPhysicalDeviceVulkan13Properties::integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated);
            integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated        = &(VkPhysicalDeviceVulkan13Properties::integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated);
            integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated          = &(VkPhysicalDeviceVulkan13Properties::integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated);
            integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated = &(VkPhysicalDeviceVulkan13Properties::integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated);
            integerDotProductAccumulatingSaturating16BitUnsignedAccelerated               = &(VkPhysicalDeviceVulkan13Properties::integerDotProductAccumulatingSaturating16BitUnsignedAccelerated);
            integerDotProductAccumulatingSaturating16BitSignedAccelerated                 = &(VkPhysicalDeviceVulkan13Properties::integerDotProductAccumulatingSaturating16BitSignedAccelerated);
            integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerated        = &(VkPhysicalDeviceVulkan13Properties::integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerated);
            integerDotProductAccumulatingSaturating32BitUnsignedAccelerated               = &(VkPhysicalDeviceVulkan13Properties::integerDotProductAccumulatingSaturating32BitUnsignedAccelerated);
            integerDotProductAccumulatingSaturating32BitSignedAccelerated                 = &(VkPhysicalDeviceVulkan13Properties::integerDotProductAccumulatingSaturating32BitSignedAccelerated);
            integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerated        = &(VkPhysicalDeviceVulkan13Properties::integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerated);
            integerDotProductAccumulatingSaturating64BitUnsignedAccelerated               = &(VkPhysicalDeviceVulkan13Properties::integerDotProductAccumulatingSaturating64BitUnsignedAccelerated);
            integerDotProductAccumulatingSaturating64BitSignedAccelerated                 = &(VkPhysicalDeviceVulkan13Properties::integerDotProductAccumulatingSaturating64BitSignedAccelerated);
            integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerated        = &(VkPhysicalDeviceVulkan13Properties::integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerated);
            storageTexelBufferOffsetAlignmentBytes                                        = &(VkPhysicalDeviceVulkan13Properties::storageTexelBufferOffsetAlignmentBytes);
            storageTexelBufferOffsetSingleTexelAlignment                                  = &(VkPhysicalDeviceVulkan13Properties::storageTexelBufferOffsetSingleTexelAlignment);
            uniformTexelBufferOffsetAlignmentBytes                                        = &(VkPhysicalDeviceVulkan13Properties::uniformTexelBufferOffsetAlignmentBytes);
            uniformTexelBufferOffsetSingleTexelAlignment                                  = &(VkPhysicalDeviceVulkan13Properties::uniformTexelBufferOffsetSingleTexelAlignment);
            maxBufferSize                                                                 = &(VkPhysicalDeviceVulkan13Properties::maxBufferSize);

            VkPhysicalDeviceVulkan13Properties::pNext = nullptr;

            return;
        }


        minSubgroupSize                                                               = &(VkPhysicalDeviceSubgroupSizeControlProperties::minSubgroupSize);
        maxSubgroupSize                                                               = &(VkPhysicalDeviceSubgroupSizeControlProperties::maxSubgroupSize);
        maxComputeWorkgroupSubgroups                                                  = &(VkPhysicalDeviceSubgroupSizeControlProperties::maxComputeWorkgroupSubgroups);
        requiredSubgroupSizeStages                                                    = &(VkPhysicalDeviceSubgroupSizeControlProperties::requiredSubgroupSizeStages);
        maxInlineUniformBlockSize                                                     = &(VkPhysicalDeviceInlineUniformBlockProperties::maxInlineUniformBlockSize);
        maxPerStageDescriptorInlineUniformBlocks                                      = &(VkPhysicalDeviceInlineUniformBlockProperties::maxPerStageDescriptorInlineUniformBlocks);
        maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks                       = &(VkPhysicalDeviceInlineUniformBlockProperties::maxPerStageDescriptorUpdateAfterBindInlineUniformBlocks);
        maxDescriptorSetInlineUniformBlocks                                           = &(VkPhysicalDeviceInlineUniformBlockProperties::maxDescriptorSetInlineUniformBlocks);
        maxDescriptorSetUpdateAfterBindInlineUniformBlocks                            = &(VkPhysicalDeviceInlineUniformBlockProperties::maxDescriptorSetUpdateAfterBindInlineUniformBlocks);
        integerDotProduct8BitUnsignedAccelerated                                      = &(VkPhysicalDeviceShaderIntegerDotProductProperties::integerDotProduct8BitUnsignedAccelerated);
        integerDotProduct8BitSignedAccelerated                                        = &(VkPhysicalDeviceShaderIntegerDotProductProperties::integerDotProduct8BitSignedAccelerated);
        integerDotProduct8BitMixedSignednessAccelerated                               = &(VkPhysicalDeviceShaderIntegerDotProductProperties::integerDotProduct8BitMixedSignednessAccelerated);
        integerDotProduct4x8BitPackedUnsignedAccelerated                              = &(VkPhysicalDeviceShaderIntegerDotProductProperties::integerDotProduct4x8BitPackedUnsignedAccelerated);
        integerDotProduct4x8BitPackedSignedAccelerated                                = &(VkPhysicalDeviceShaderIntegerDotProductProperties::integerDotProduct4x8BitPackedSignedAccelerated);
        integerDotProduct4x8BitPackedMixedSignednessAccelerated                       = &(VkPhysicalDeviceShaderIntegerDotProductProperties::integerDotProduct4x8BitPackedMixedSignednessAccelerated);
        integerDotProduct16BitUnsignedAccelerated                                     = &(VkPhysicalDeviceShaderIntegerDotProductProperties::integerDotProduct16BitUnsignedAccelerated);
        integerDotProduct16BitSignedAccelerated                                       = &(VkPhysicalDeviceShaderIntegerDotProductProperties::integerDotProduct16BitSignedAccelerated);
        integerDotProduct16BitMixedSignednessAccelerated                              = &(VkPhysicalDeviceShaderIntegerDotProductProperties::integerDotProduct16BitMixedSignednessAccelerated);
        integerDotProduct32BitUnsignedAccelerated                                     = &(VkPhysicalDeviceShaderIntegerDotProductProperties::integerDotProduct32BitUnsignedAccelerated);
        integerDotProduct32BitSignedAccelerated                                       = &(VkPhysicalDeviceShaderIntegerDotProductProperties::integerDotProduct32BitSignedAccelerated);
        integerDotProduct32BitMixedSignednessAccelerated                              = &(VkPhysicalDeviceShaderIntegerDotProductProperties::integerDotProduct32BitMixedSignednessAccelerated);
        integerDotProduct64BitUnsignedAccelerated                                     = &(VkPhysicalDeviceShaderIntegerDotProductProperties::integerDotProduct64BitUnsignedAccelerated);
        integerDotProduct64BitSignedAccelerated                                       = &(VkPhysicalDeviceShaderIntegerDotProductProperties::integerDotProduct64BitSignedAccelerated);
        integerDotProduct64BitMixedSignednessAccelerated                              = &(VkPhysicalDeviceShaderIntegerDotProductProperties::integerDotProduct64BitMixedSignednessAccelerated);
        integerDotProductAccumulatingSaturating8BitUnsignedAccelerated                = &(VkPhysicalDeviceShaderIntegerDotProductProperties::integerDotProductAccumulatingSaturating8BitUnsignedAccelerated);
        integerDotProductAccumulatingSaturating8BitSignedAccelerated                  = &(VkPhysicalDeviceShaderIntegerDotProductProperties::integerDotProductAccumulatingSaturating8BitSignedAccelerated);
        integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated         = &(VkPhysicalDeviceShaderIntegerDotProductProperties::integerDotProductAccumulatingSaturating8BitMixedSignednessAccelerated);
        integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated        = &(VkPhysicalDeviceShaderIntegerDotProductProperties::integerDotProductAccumulatingSaturating4x8BitPackedUnsignedAccelerated);
        integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated          = &(VkPhysicalDeviceShaderIntegerDotProductProperties::integerDotProductAccumulatingSaturating4x8BitPackedSignedAccelerated);
        integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated = &(VkPhysicalDeviceShaderIntegerDotProductProperties::integerDotProductAccumulatingSaturating4x8BitPackedMixedSignednessAccelerated);
        integerDotProductAccumulatingSaturating16BitUnsignedAccelerated               = &(VkPhysicalDeviceShaderIntegerDotProductProperties::integerDotProductAccumulatingSaturating16BitUnsignedAccelerated);
        integerDotProductAccumulatingSaturating16BitSignedAccelerated                 = &(VkPhysicalDeviceShaderIntegerDotProductProperties::integerDotProductAccumulatingSaturating16BitSignedAccelerated);
        integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerated        = &(VkPhysicalDeviceShaderIntegerDotProductProperties::integerDotProductAccumulatingSaturating16BitMixedSignednessAccelerated);
        integerDotProductAccumulatingSaturating32BitUnsignedAccelerated               = &(VkPhysicalDeviceShaderIntegerDotProductProperties::integerDotProductAccumulatingSaturating32BitUnsignedAccelerated);
        integerDotProductAccumulatingSaturating32BitSignedAccelerated                 = &(VkPhysicalDeviceShaderIntegerDotProductProperties::integerDotProductAccumulatingSaturating32BitSignedAccelerated);
        integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerated        = &(VkPhysicalDeviceShaderIntegerDotProductProperties::integerDotProductAccumulatingSaturating32BitMixedSignednessAccelerated);
        integerDotProductAccumulatingSaturating64BitUnsignedAccelerated               = &(VkPhysicalDeviceShaderIntegerDotProductProperties::integerDotProductAccumulatingSaturating64BitUnsignedAccelerated);
        integerDotProductAccumulatingSaturating64BitSignedAccelerated                 = &(VkPhysicalDeviceShaderIntegerDotProductProperties::integerDotProductAccumulatingSaturating64BitSignedAccelerated);
        integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerated        = &(VkPhysicalDeviceShaderIntegerDotProductProperties::integerDotProductAccumulatingSaturating64BitMixedSignednessAccelerated);
        storageTexelBufferOffsetAlignmentBytes                                        = &(VkPhysicalDeviceTexelBufferAlignmentProperties::storageTexelBufferOffsetAlignmentBytes);
        storageTexelBufferOffsetSingleTexelAlignment                                  = &(VkPhysicalDeviceTexelBufferAlignmentProperties::storageTexelBufferOffsetSingleTexelAlignment);
        uniformTexelBufferOffsetAlignmentBytes                                        = &(VkPhysicalDeviceTexelBufferAlignmentProperties::uniformTexelBufferOffsetAlignmentBytes);
        uniformTexelBufferOffsetSingleTexelAlignment                                  = &(VkPhysicalDeviceTexelBufferAlignmentProperties::uniformTexelBufferOffsetSingleTexelAlignment);
        maxBufferSize                                                                 = &(VkPhysicalDeviceMaintenance4Properties::maxBufferSize);

        // These features are only available in 1.3 Core
//      maxInlineUniformTotalSize                                                     = &(VkPhysicalDeviceVulkan13Properties::maxInlineUniformTotalSize);

        VkPhysicalDeviceSubgroupSizeControlProperties::pNext     = static_cast<VkPhysicalDeviceInlineUniformBlockProperties*>(this);
        VkPhysicalDeviceInlineUniformBlockProperties::pNext      = static_cast<VkPhysicalDeviceShaderIntegerDotProductProperties*>(this);
        VkPhysicalDeviceShaderIntegerDotProductProperties::pNext = static_cast<VkPhysicalDeviceTexelBufferAlignmentProperties*>(this);
        VkPhysicalDeviceTexelBufferAlignmentProperties::pNext    = static_cast<VkPhysicalDeviceMaintenance4Properties*>(this);
        VkPhysicalDeviceMaintenance4Properties::pNext            = nullptr;
    }
};

///
/// \brief Core 1.4 Properties
struct device_properties_14 : private VkPhysicalDeviceVulkan14Properties,
                              private VkPhysicalDeviceLineRasterizationProperties,
                              private VkPhysicalDeviceVertexAttributeDivisorProperties,
                              private VkPhysicalDevicePushDescriptorProperties,
                              private VkPhysicalDeviceMaintenance5Properties,
                              private VkPhysicalDeviceMaintenance6Properties,
                              private VkPhysicalDevicePipelineRobustnessProperties,
                              private VkPhysicalDeviceHostImageCopyProperties {

// Public References ---------------------------------------------------------------------------------------------------
public:

    /// \name Properties
    /// @{

    uint32_t*                           lineSubPixelPrecisionBits;
    uint32_t*                           maxVertexAttribDivisor;
    VkBool32*                           supportsNonZeroFirstInstance;
    uint32_t*                           maxPushDescriptors;
    VkBool32*                           dynamicRenderingLocalReadDepthStencilAttachments;
    VkBool32*                           dynamicRenderingLocalReadMultisampledAttachments;
    VkBool32*                           earlyFragmentMultisampleCoverageAfterSampleCounting;
    VkBool32*                           earlyFragmentSampleMaskTestBeforeSampleCounting;
    VkBool32*                           depthStencilSwizzleOneSupport;
    VkBool32*                           polygonModePointSize;
    VkBool32*                           nonStrictSinglePixelWideLinesUseParallelogram;
    VkBool32*                           nonStrictWideLinesUseParallelogram;
    VkBool32*                           blockTexelViewCompatibleMultipleLayers;
    uint32_t*                           maxCombinedImageSamplerDescriptorCount;
    VkBool32*                           fragmentShadingRateClampCombinerInputs;
    VkPipelineRobustnessBufferBehavior* defaultRobustnessStorageBuffers;
    VkPipelineRobustnessBufferBehavior* defaultRobustnessUniformBuffers;
    VkPipelineRobustnessBufferBehavior* defaultRobustnessVertexInputs;
    VkPipelineRobustnessImageBehavior*  defaultRobustnessImages;
    uint32_t*                           copySrcLayoutCount;
    VkImageLayout**                     pCopySrcLayouts;
    uint32_t*                           copyDstLayoutCount;
    VkImageLayout**                     pCopyDstLayouts;
    uint8_t (*                          optimalTilingLayoutUUID)[VK_UUID_SIZE];
    VkBool32*                           identicalMemoryTypeRequirements;
    VkBool32                            useCore;

    /// @}


// Methods -------------------------------------------------------------------------------------------------------------
public:
    device_properties_14() = delete;

    device_properties_14(const VkPhysicalDeviceProperties& core)
        : VkPhysicalDeviceVulkan14Properties { }
        , VkPhysicalDeviceLineRasterizationProperties { }
        , VkPhysicalDeviceVertexAttributeDivisorProperties { }
        , VkPhysicalDevicePushDescriptorProperties { }
        , VkPhysicalDeviceMaintenance5Properties { }
        , VkPhysicalDeviceMaintenance6Properties { }
        , VkPhysicalDevicePipelineRobustnessProperties { }
        , VkPhysicalDeviceHostImageCopyProperties { }
        , lineSubPixelPrecisionBits { nullptr }
        , maxVertexAttribDivisor { nullptr }
        , supportsNonZeroFirstInstance { nullptr }
        , maxPushDescriptors { nullptr }
        , dynamicRenderingLocalReadDepthStencilAttachments { nullptr }
        , dynamicRenderingLocalReadMultisampledAttachments { nullptr }
        , earlyFragmentMultisampleCoverageAfterSampleCounting { nullptr }
        , earlyFragmentSampleMaskTestBeforeSampleCounting { nullptr }
        , depthStencilSwizzleOneSupport { nullptr }
        , polygonModePointSize { nullptr }
        , nonStrictSinglePixelWideLinesUseParallelogram { nullptr }
        , nonStrictWideLinesUseParallelogram { nullptr }
        , blockTexelViewCompatibleMultipleLayers { nullptr }
        , maxCombinedImageSamplerDescriptorCount { nullptr }
        , fragmentShadingRateClampCombinerInputs { nullptr }
        , defaultRobustnessStorageBuffers { nullptr }
        , defaultRobustnessUniformBuffers { nullptr }
        , defaultRobustnessVertexInputs { nullptr }
        , defaultRobustnessImages { nullptr }
        , copySrcLayoutCount { nullptr }
        , pCopySrcLayouts { nullptr }
        , copyDstLayoutCount { nullptr }
        , pCopyDstLayouts { nullptr }
        , optimalTilingLayoutUUID { nullptr }
        , identicalMemoryTypeRequirements { nullptr }
        , useCore { core.apiVersion >= VK_API_VERSION_1_4 } {

        _clear();
        _link();
    }

    device_properties_14(const device_properties_14& properties)
        : VkPhysicalDeviceVulkan14Properties { properties }
        , VkPhysicalDeviceLineRasterizationProperties { properties }
        , VkPhysicalDeviceVertexAttributeDivisorProperties { properties }
        , VkPhysicalDevicePushDescriptorProperties { properties }
        , VkPhysicalDeviceMaintenance5Properties { properties }
        , VkPhysicalDeviceMaintenance6Properties { properties }
        , VkPhysicalDevicePipelineRobustnessProperties { properties }
        , VkPhysicalDeviceHostImageCopyProperties { properties }
        , lineSubPixelPrecisionBits { nullptr }
        , maxVertexAttribDivisor { nullptr }
        , supportsNonZeroFirstInstance { nullptr }
        , maxPushDescriptors { nullptr }
        , dynamicRenderingLocalReadDepthStencilAttachments { nullptr }
        , dynamicRenderingLocalReadMultisampledAttachments { nullptr }
        , earlyFragmentMultisampleCoverageAfterSampleCounting { nullptr }
        , earlyFragmentSampleMaskTestBeforeSampleCounting { nullptr }
        , depthStencilSwizzleOneSupport { nullptr }
        , polygonModePointSize { nullptr }
        , nonStrictSinglePixelWideLinesUseParallelogram { nullptr }
        , nonStrictWideLinesUseParallelogram { nullptr }
        , blockTexelViewCompatibleMultipleLayers { nullptr }
        , maxCombinedImageSamplerDescriptorCount { nullptr }
        , fragmentShadingRateClampCombinerInputs { nullptr }
        , defaultRobustnessStorageBuffers { nullptr }
        , defaultRobustnessUniformBuffers { nullptr }
        , defaultRobustnessVertexInputs { nullptr }
        , defaultRobustnessImages { nullptr }
        , copySrcLayoutCount { nullptr }
        , pCopySrcLayouts { nullptr }
        , copyDstLayoutCount { nullptr }
        , pCopyDstLayouts { nullptr }
        , optimalTilingLayoutUUID { nullptr }
        , identicalMemoryTypeRequirements { nullptr }
        , useCore { properties.useCore } {

        _link();
    }

    device_properties_14& operator=(const device_properties_14& properties) {
        if (&properties == this) {
            return *this;
        }

        VkPhysicalDeviceVulkan14Properties::operator=(properties);
        VkPhysicalDeviceLineRasterizationProperties::operator=(properties);
        VkPhysicalDeviceVertexAttributeDivisorProperties::operator=(properties);
        VkPhysicalDevicePushDescriptorProperties::operator=(properties);
        VkPhysicalDeviceMaintenance5Properties::operator=(properties);
        VkPhysicalDeviceMaintenance6Properties::operator=(properties);
        VkPhysicalDevicePipelineRobustnessProperties::operator=(properties);
        VkPhysicalDeviceHostImageCopyProperties::operator=(properties);

        _link();

        return *this;
    }

    ///
    /// \brief Chain an extension structure
    /// \param next
    void chain(void* next) {

        if (useCore) {
            VkPhysicalDeviceVulkan14Properties::pNext = next;
        } else {
            VkPhysicalDeviceHostImageCopyProperties::pNext = next;
        }
    }

    ///
    /// \brief Implicit casting for chaining
    operator void*() {

        if (useCore) {
            return static_cast<VkPhysicalDeviceVulkan14Properties*>(this);
        } else {
            return static_cast<VkPhysicalDeviceVertexAttributeDivisorProperties*>(this);
        }
    }


// Helpers -------------------------------------------------------------------------------------------------------------
private:

    void _clear() {

        // Clear the structure
        fennec::memset(this, 0, sizeof(*this));

        // Set the structure types
        VkPhysicalDeviceVulkan14Properties::sType               = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_4_PROPERTIES;
        VkPhysicalDeviceLineRasterizationProperties::sType      = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LINE_RASTERIZATION_PROPERTIES;
        VkPhysicalDeviceVertexAttributeDivisorProperties::sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES;
        VkPhysicalDevicePushDescriptorProperties::sType         = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PUSH_DESCRIPTOR_PROPERTIES;
        VkPhysicalDeviceMaintenance5Properties::sType           = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_5_PROPERTIES;
        VkPhysicalDeviceMaintenance6Properties::sType           = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_6_PROPERTIES;
        VkPhysicalDevicePipelineRobustnessProperties::sType     = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_ROBUSTNESS_PROPERTIES;
        VkPhysicalDeviceHostImageCopyProperties::sType          = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_IMAGE_COPY_PROPERTIES;
    }

    void _link() {

        // Check if we are Core 1.4 or later
        if (useCore) {

            // Link to Core Structure
            lineSubPixelPrecisionBits                           = &(VkPhysicalDeviceVulkan14Properties::lineSubPixelPrecisionBits);
            maxVertexAttribDivisor                              = &(VkPhysicalDeviceVulkan14Properties::maxVertexAttribDivisor);
            supportsNonZeroFirstInstance                        = &(VkPhysicalDeviceVulkan14Properties::supportsNonZeroFirstInstance);
            maxPushDescriptors                                  = &(VkPhysicalDeviceVulkan14Properties::maxPushDescriptors);
            dynamicRenderingLocalReadDepthStencilAttachments    = &(VkPhysicalDeviceVulkan14Properties::dynamicRenderingLocalReadDepthStencilAttachments);
            dynamicRenderingLocalReadMultisampledAttachments    = &(VkPhysicalDeviceVulkan14Properties::dynamicRenderingLocalReadMultisampledAttachments);
            earlyFragmentMultisampleCoverageAfterSampleCounting = &(VkPhysicalDeviceVulkan14Properties::earlyFragmentMultisampleCoverageAfterSampleCounting);
            earlyFragmentSampleMaskTestBeforeSampleCounting     = &(VkPhysicalDeviceVulkan14Properties::earlyFragmentSampleMaskTestBeforeSampleCounting);
            depthStencilSwizzleOneSupport                       = &(VkPhysicalDeviceVulkan14Properties::depthStencilSwizzleOneSupport);
            polygonModePointSize                                = &(VkPhysicalDeviceVulkan14Properties::polygonModePointSize);
            nonStrictSinglePixelWideLinesUseParallelogram       = &(VkPhysicalDeviceVulkan14Properties::nonStrictSinglePixelWideLinesUseParallelogram);
            nonStrictWideLinesUseParallelogram                  = &(VkPhysicalDeviceVulkan14Properties::nonStrictWideLinesUseParallelogram);
            blockTexelViewCompatibleMultipleLayers              = &(VkPhysicalDeviceVulkan14Properties::blockTexelViewCompatibleMultipleLayers);
            maxCombinedImageSamplerDescriptorCount              = &(VkPhysicalDeviceVulkan14Properties::maxCombinedImageSamplerDescriptorCount);
            fragmentShadingRateClampCombinerInputs              = &(VkPhysicalDeviceVulkan14Properties::fragmentShadingRateClampCombinerInputs);
            defaultRobustnessStorageBuffers                     = &(VkPhysicalDeviceVulkan14Properties::defaultRobustnessStorageBuffers);
            defaultRobustnessUniformBuffers                     = &(VkPhysicalDeviceVulkan14Properties::defaultRobustnessUniformBuffers);
            defaultRobustnessVertexInputs                       = &(VkPhysicalDeviceVulkan14Properties::defaultRobustnessVertexInputs);
            defaultRobustnessImages                             = &(VkPhysicalDeviceVulkan14Properties::defaultRobustnessImages);
            copySrcLayoutCount                                  = &(VkPhysicalDeviceVulkan14Properties::copySrcLayoutCount);
            pCopySrcLayouts                                     = &(VkPhysicalDeviceVulkan14Properties::pCopySrcLayouts);
            copyDstLayoutCount                                  = &(VkPhysicalDeviceVulkan14Properties::copyDstLayoutCount);
            pCopyDstLayouts                                     = &(VkPhysicalDeviceVulkan14Properties::pCopyDstLayouts);
            optimalTilingLayoutUUID                             = &(VkPhysicalDeviceVulkan14Properties::optimalTilingLayoutUUID);
            identicalMemoryTypeRequirements                     = &(VkPhysicalDeviceVulkan14Properties::identicalMemoryTypeRequirements);

            VkPhysicalDeviceVulkan14Properties::pNext = nullptr;

            return;
        }

        // Link to Extension Structures
        lineSubPixelPrecisionBits                           = &(VkPhysicalDeviceLineRasterizationProperties::lineSubPixelPrecisionBits);
        maxVertexAttribDivisor                              = &(VkPhysicalDeviceVertexAttributeDivisorProperties::maxVertexAttribDivisor);
        supportsNonZeroFirstInstance                        = &(VkPhysicalDeviceVertexAttributeDivisorProperties::supportsNonZeroFirstInstance);
        maxPushDescriptors                                  = &(VkPhysicalDevicePushDescriptorProperties::maxPushDescriptors);
        earlyFragmentMultisampleCoverageAfterSampleCounting = &(VkPhysicalDeviceMaintenance5Properties::earlyFragmentMultisampleCoverageAfterSampleCounting);
        earlyFragmentSampleMaskTestBeforeSampleCounting     = &(VkPhysicalDeviceMaintenance5Properties::earlyFragmentSampleMaskTestBeforeSampleCounting);
        depthStencilSwizzleOneSupport                       = &(VkPhysicalDeviceMaintenance5Properties::depthStencilSwizzleOneSupport);
        polygonModePointSize                                = &(VkPhysicalDeviceMaintenance5Properties::polygonModePointSize);
        nonStrictSinglePixelWideLinesUseParallelogram       = &(VkPhysicalDeviceMaintenance5Properties::nonStrictSinglePixelWideLinesUseParallelogram);
        nonStrictWideLinesUseParallelogram                  = &(VkPhysicalDeviceMaintenance5Properties::nonStrictWideLinesUseParallelogram);
        blockTexelViewCompatibleMultipleLayers              = &(VkPhysicalDeviceMaintenance6Properties::blockTexelViewCompatibleMultipleLayers);
        maxCombinedImageSamplerDescriptorCount              = &(VkPhysicalDeviceMaintenance6Properties::maxCombinedImageSamplerDescriptorCount);
        fragmentShadingRateClampCombinerInputs              = &(VkPhysicalDeviceMaintenance6Properties::fragmentShadingRateClampCombinerInputs);
        defaultRobustnessStorageBuffers                     = &(VkPhysicalDevicePipelineRobustnessProperties::defaultRobustnessStorageBuffers);
        defaultRobustnessUniformBuffers                     = &(VkPhysicalDevicePipelineRobustnessProperties::defaultRobustnessUniformBuffers);
        defaultRobustnessVertexInputs                       = &(VkPhysicalDevicePipelineRobustnessProperties::defaultRobustnessVertexInputs);
        defaultRobustnessImages                             = &(VkPhysicalDevicePipelineRobustnessProperties::defaultRobustnessImages);
        copySrcLayoutCount                                  = &(VkPhysicalDeviceHostImageCopyProperties::copySrcLayoutCount);
        pCopySrcLayouts                                     = &(VkPhysicalDeviceHostImageCopyProperties::pCopySrcLayouts);
        copyDstLayoutCount                                  = &(VkPhysicalDeviceHostImageCopyProperties::copyDstLayoutCount);
        pCopyDstLayouts                                     = &(VkPhysicalDeviceHostImageCopyProperties::pCopyDstLayouts);
        optimalTilingLayoutUUID                             = &(VkPhysicalDeviceHostImageCopyProperties::optimalTilingLayoutUUID);
        identicalMemoryTypeRequirements                     = &(VkPhysicalDeviceHostImageCopyProperties::identicalMemoryTypeRequirements);

        // These features are only available in 1.4 Core
//      dynamicRenderingLocalReadDepthStencilAttachments    = &(VkPhysicalDeviceVulkan14Properties::dynamicRenderingLocalReadDepthStencilAttachments);
//      dynamicRenderingLocalReadMultisampledAttachments    = &(VkPhysicalDeviceVulkan14Properties::dynamicRenderingLocalReadMultisampledAttachments);

        // Daisy Chain
        VkPhysicalDeviceLineRasterizationProperties::pNext      = static_cast<VkPhysicalDeviceVertexAttributeDivisorProperties*>(this);
        VkPhysicalDeviceVertexAttributeDivisorProperties::pNext = static_cast<VkPhysicalDevicePushDescriptorProperties*>(this);
        VkPhysicalDevicePushDescriptorProperties::pNext         = static_cast<VkPhysicalDeviceMaintenance5Properties*>(this);
        VkPhysicalDeviceMaintenance5Properties::pNext           = static_cast<VkPhysicalDeviceMaintenance6Properties*>(this);
        VkPhysicalDeviceMaintenance6Properties::pNext           = static_cast<VkPhysicalDevicePipelineRobustnessProperties*>(this);
        VkPhysicalDevicePipelineRobustnessProperties::pNext     = static_cast<VkPhysicalDeviceHostImageCopyProperties*>(this);
        VkPhysicalDeviceHostImageCopyProperties::pNext          = nullptr;
    }
};

///
/// \brief KHR Properties
struct device_properties_khr : private VkPhysicalDeviceAccelerationStructurePropertiesKHR,
                               private VkPhysicalDeviceComputeShaderDerivativesPropertiesKHR,
                               private VkPhysicalDeviceCooperativeMatrixPropertiesKHR,
                               private VkPhysicalDeviceCopyMemoryIndirectPropertiesKHR,
                               private VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR,
                               private VkPhysicalDeviceFragmentShadingRatePropertiesKHR,
                               private VkPhysicalDeviceLayeredApiPropertiesListKHR,
                               private VkPhysicalDeviceLayeredApiVulkanPropertiesKHR,
                               private VkPhysicalDeviceMaintenance7PropertiesKHR,
                               private VkPhysicalDeviceMaintenance9PropertiesKHR,
                               private VkPhysicalDeviceMaintenance10PropertiesKHR,
                               private VkPhysicalDevicePerformanceQueryPropertiesKHR,
                               private VkPhysicalDevicePipelineBinaryPropertiesKHR,
                               private VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR,
                               private VkPhysicalDeviceRayTracingPipelinePropertiesKHR,
                               private VkPhysicalDeviceRobustness2PropertiesKHR {

// Public References ---------------------------------------------------------------------------------------------------
public:

    /// \name Properties
    /// @{

    uint64_t*                                 maxGeometryCount;
    uint64_t*                                 maxInstanceCount;
    uint64_t*                                 maxPrimitiveCount;
    uint32_t*                                 maxPerStageDescriptorAccelerationStructures;
    uint32_t*                                 maxPerStageDescriptorUpdateAfterBindAccelerationStructures;
    uint32_t*                                 maxDescriptorSetAccelerationStructures;
    uint32_t*                                 maxDescriptorSetUpdateAfterBindAccelerationStructures;
    uint32_t*                                 minAccelerationStructureScratchOffsetAlignment;
    VkBool32*                                 meshAndTaskShaderDerivatives;
    VkShaderStageFlags*                       cooperativeMatrixSupportedStages;
    VkQueueFlags*                             supportedCopyQueues;
    VkBool32*                                 triStripVertexOrderIndependentOfProvokingVertex;
    VkExtent2D*                               minFragmentShadingRateAttachmentTexelSize;
    VkExtent2D*                               maxFragmentShadingRateAttachmentTexelSize;
    uint32_t*                                 maxFragmentShadingRateAttachmentTexelSizeAspectRatio;
    VkBool32*                                 primitiveFragmentShadingRateWithMultipleViewports;
    VkBool32*                                 layeredShadingRateAttachments;
    VkBool32*                                 fragmentShadingRateNonTrivialCombinerOps;
    VkExtent2D*                               maxFragmentSize;
    uint32_t*                                 maxFragmentSizeAspectRatio;
    uint32_t*                                 maxFragmentShadingRateCoverageSamples;
    VkSampleCountFlagBits*                    maxFragmentShadingRateRasterizationSamples;
    VkBool32*                                 fragmentShadingRateWithShaderDepthStencilWrites;
    VkBool32*                                 fragmentShadingRateWithSampleMask;
    VkBool32*                                 fragmentShadingRateWithShaderSampleMask;
    VkBool32*                                 fragmentShadingRateWithConservativeRasterization;
    VkBool32*                                 fragmentShadingRateWithFragmentShaderInterlock;
    VkBool32*                                 fragmentShadingRateWithCustomSampleLocations;
    VkBool32*                                 fragmentShadingRateStrictMultiplyCombiner;
    uint32_t*                                 layeredApiCount;
    VkPhysicalDeviceLayeredApiPropertiesKHR** pLayeredApis;
    VkPhysicalDeviceProperties2*              layerProperties;
    VkBool32*                                 robustFragmentShadingRateAttachmentAccess;
    VkBool32*                                 separateDepthStencilAttachmentAccess;
    uint32_t*                                 maxDescriptorSetTotalUniformBuffersDynamic;
    uint32_t*                                 maxDescriptorSetTotalStorageBuffersDynamic;
    uint32_t*                                 maxDescriptorSetTotalBuffersDynamic;
    uint32_t*                                 maxDescriptorSetUpdateAfterBindTotalUniformBuffersDynamic;
    uint32_t*                                 maxDescriptorSetUpdateAfterBindTotalStorageBuffersDynamic;
    uint32_t*                                 maxDescriptorSetUpdateAfterBindTotalBuffersDynamic;
    VkBool32*                                 image2DViewOf3DSparse;
    VkDefaultVertexAttributeValueKHR*         defaultVertexAttributeValue;
    VkBool32*                                 rgba4OpaqueBlackSwizzled;
    VkBool32*                                 resolveSrgbFormatAppliesTransferFunction;
    VkBool32*                                 resolveSrgbFormatSupportsTransferFunctionControl;
    VkBool32*                                 allowCommandBufferQueryCopies;
    VkBool32*                                 pipelineBinaryInternalCache;
    VkBool32*                                 pipelineBinaryInternalCacheControl;
    VkBool32*                                 pipelineBinaryPrefersInternalCache;
    VkBool32*                                 pipelineBinaryPrecompiledInternalCache;
    VkBool32*                                 pipelineBinaryCompressedData;
    VkBool32*                                 pipelineExecutableInfo;
    uint32_t*                                 shaderGroupHandleSize;
    uint32_t*                                 maxRayRecursionDepth;
    uint32_t*                                 maxShaderGroupStride;
    uint32_t*                                 shaderGroupBaseAlignment;
    uint32_t*                                 shaderGroupHandleCaptureReplaySize;
    uint32_t*                                 maxRayDispatchInvocationCount;
    uint32_t*                                 shaderGroupHandleAlignment;
    uint32_t*                                 maxRayHitAttributeSize;
    VkDeviceSize*                             robustStorageBufferAccessSizeAlignment;
    VkDeviceSize*                             robustUniformBufferAccessSizeAlignment;

    /// @}


// Methods -------------------------------------------------------------------------------------------------------------
public:

    device_properties_khr()
        : VkPhysicalDeviceAccelerationStructurePropertiesKHR { }
        , VkPhysicalDeviceComputeShaderDerivativesPropertiesKHR { }
        , VkPhysicalDeviceCooperativeMatrixPropertiesKHR { }
        , VkPhysicalDeviceCopyMemoryIndirectPropertiesKHR { }
        , VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR { }
        , VkPhysicalDeviceFragmentShadingRatePropertiesKHR { }
        , VkPhysicalDeviceLayeredApiPropertiesListKHR { }
        , VkPhysicalDeviceLayeredApiVulkanPropertiesKHR { }
        , VkPhysicalDeviceMaintenance7PropertiesKHR { }
        , VkPhysicalDeviceMaintenance9PropertiesKHR { }
        , VkPhysicalDeviceMaintenance10PropertiesKHR { }
        , VkPhysicalDevicePerformanceQueryPropertiesKHR { }
        , VkPhysicalDevicePipelineBinaryPropertiesKHR { }
        , VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR { }
        , VkPhysicalDeviceRayTracingPipelinePropertiesKHR { }
        , VkPhysicalDeviceRobustness2PropertiesKHR { }
        , maxGeometryCount { nullptr }
        , maxInstanceCount { nullptr }
        , maxPrimitiveCount { nullptr }
        , maxPerStageDescriptorAccelerationStructures { nullptr }
        , maxPerStageDescriptorUpdateAfterBindAccelerationStructures { nullptr }
        , maxDescriptorSetAccelerationStructures { nullptr }
        , maxDescriptorSetUpdateAfterBindAccelerationStructures { nullptr }
        , minAccelerationStructureScratchOffsetAlignment { nullptr }
        , meshAndTaskShaderDerivatives { nullptr }
        , cooperativeMatrixSupportedStages { nullptr }
        , supportedCopyQueues { nullptr }
        , triStripVertexOrderIndependentOfProvokingVertex { nullptr }
        , minFragmentShadingRateAttachmentTexelSize { nullptr }
        , maxFragmentShadingRateAttachmentTexelSize { nullptr }
        , maxFragmentShadingRateAttachmentTexelSizeAspectRatio { nullptr }
        , primitiveFragmentShadingRateWithMultipleViewports { nullptr }
        , layeredShadingRateAttachments { nullptr }
        , fragmentShadingRateNonTrivialCombinerOps { nullptr }
        , maxFragmentSize { nullptr }
        , maxFragmentSizeAspectRatio { nullptr }
        , maxFragmentShadingRateCoverageSamples { nullptr }
        , maxFragmentShadingRateRasterizationSamples { nullptr }
        , fragmentShadingRateWithShaderDepthStencilWrites { nullptr }
        , fragmentShadingRateWithSampleMask { nullptr }
        , fragmentShadingRateWithShaderSampleMask { nullptr }
        , fragmentShadingRateWithConservativeRasterization { nullptr }
        , fragmentShadingRateWithFragmentShaderInterlock { nullptr }
        , fragmentShadingRateWithCustomSampleLocations { nullptr }
        , fragmentShadingRateStrictMultiplyCombiner { nullptr }
        , layeredApiCount { nullptr }
        , pLayeredApis { nullptr }
        , layerProperties { nullptr }
        , robustFragmentShadingRateAttachmentAccess { nullptr }
        , separateDepthStencilAttachmentAccess { nullptr }
        , maxDescriptorSetTotalUniformBuffersDynamic { nullptr }
        , maxDescriptorSetTotalStorageBuffersDynamic { nullptr }
        , maxDescriptorSetTotalBuffersDynamic { nullptr }
        , maxDescriptorSetUpdateAfterBindTotalUniformBuffersDynamic { nullptr }
        , maxDescriptorSetUpdateAfterBindTotalStorageBuffersDynamic { nullptr }
        , maxDescriptorSetUpdateAfterBindTotalBuffersDynamic { nullptr }
        , image2DViewOf3DSparse { nullptr }
        , defaultVertexAttributeValue { nullptr }
        , rgba4OpaqueBlackSwizzled { nullptr }
        , resolveSrgbFormatAppliesTransferFunction { nullptr }
        , resolveSrgbFormatSupportsTransferFunctionControl { nullptr }
        , allowCommandBufferQueryCopies { nullptr }
        , pipelineBinaryInternalCache { nullptr }
        , pipelineBinaryInternalCacheControl { nullptr }
        , pipelineBinaryPrefersInternalCache { nullptr }
        , pipelineBinaryPrecompiledInternalCache { nullptr }
        , pipelineBinaryCompressedData { nullptr }
        , pipelineExecutableInfo { nullptr }
        , shaderGroupHandleSize { nullptr }
        , maxRayRecursionDepth { nullptr }
        , maxShaderGroupStride { nullptr }
        , shaderGroupBaseAlignment { nullptr }
        , shaderGroupHandleCaptureReplaySize { nullptr }
        , maxRayDispatchInvocationCount { nullptr }
        , shaderGroupHandleAlignment { nullptr }
        , maxRayHitAttributeSize { nullptr }
        , robustStorageBufferAccessSizeAlignment { nullptr }
        , robustUniformBufferAccessSizeAlignment { nullptr } {

        _clear();
        _link();
    }

    device_properties_khr(const device_properties_khr& properties)
        : VkPhysicalDeviceAccelerationStructurePropertiesKHR { properties }
        , VkPhysicalDeviceComputeShaderDerivativesPropertiesKHR { properties }
        , VkPhysicalDeviceCooperativeMatrixPropertiesKHR { properties }
        , VkPhysicalDeviceCopyMemoryIndirectPropertiesKHR { properties }
        , VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR { properties }
        , VkPhysicalDeviceFragmentShadingRatePropertiesKHR { properties }
        , VkPhysicalDeviceLayeredApiPropertiesListKHR { properties }
        , VkPhysicalDeviceLayeredApiVulkanPropertiesKHR { properties }
        , VkPhysicalDeviceMaintenance7PropertiesKHR { properties }
        , VkPhysicalDeviceMaintenance9PropertiesKHR { properties }
        , VkPhysicalDeviceMaintenance10PropertiesKHR { properties }
        , VkPhysicalDevicePerformanceQueryPropertiesKHR { properties }
        , VkPhysicalDevicePipelineBinaryPropertiesKHR { properties }
        , VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR { properties }
        , VkPhysicalDeviceRayTracingPipelinePropertiesKHR { properties }
        , VkPhysicalDeviceRobustness2PropertiesKHR { properties }
        , maxGeometryCount { nullptr }
        , maxInstanceCount { nullptr }
        , maxPrimitiveCount { nullptr }
        , maxPerStageDescriptorAccelerationStructures { nullptr }
        , maxPerStageDescriptorUpdateAfterBindAccelerationStructures { nullptr }
        , maxDescriptorSetAccelerationStructures { nullptr }
        , maxDescriptorSetUpdateAfterBindAccelerationStructures { nullptr }
        , minAccelerationStructureScratchOffsetAlignment { nullptr }
        , meshAndTaskShaderDerivatives { nullptr }
        , cooperativeMatrixSupportedStages { nullptr }
        , supportedCopyQueues { nullptr }
        , triStripVertexOrderIndependentOfProvokingVertex { nullptr }
        , minFragmentShadingRateAttachmentTexelSize { nullptr }
        , maxFragmentShadingRateAttachmentTexelSize { nullptr }
        , maxFragmentShadingRateAttachmentTexelSizeAspectRatio { nullptr }
        , primitiveFragmentShadingRateWithMultipleViewports { nullptr }
        , layeredShadingRateAttachments { nullptr }
        , fragmentShadingRateNonTrivialCombinerOps { nullptr }
        , maxFragmentSize { nullptr }
        , maxFragmentSizeAspectRatio { nullptr }
        , maxFragmentShadingRateCoverageSamples { nullptr }
        , maxFragmentShadingRateRasterizationSamples { nullptr }
        , fragmentShadingRateWithShaderDepthStencilWrites { nullptr }
        , fragmentShadingRateWithSampleMask { nullptr }
        , fragmentShadingRateWithShaderSampleMask { nullptr }
        , fragmentShadingRateWithConservativeRasterization { nullptr }
        , fragmentShadingRateWithFragmentShaderInterlock { nullptr }
        , fragmentShadingRateWithCustomSampleLocations { nullptr }
        , fragmentShadingRateStrictMultiplyCombiner { nullptr }
        , layeredApiCount { nullptr }
        , pLayeredApis { nullptr }
        , layerProperties { nullptr }
        , robustFragmentShadingRateAttachmentAccess { nullptr }
        , separateDepthStencilAttachmentAccess { nullptr }
        , maxDescriptorSetTotalUniformBuffersDynamic { nullptr }
        , maxDescriptorSetTotalStorageBuffersDynamic { nullptr }
        , maxDescriptorSetTotalBuffersDynamic { nullptr }
        , maxDescriptorSetUpdateAfterBindTotalUniformBuffersDynamic { nullptr }
        , maxDescriptorSetUpdateAfterBindTotalStorageBuffersDynamic { nullptr }
        , maxDescriptorSetUpdateAfterBindTotalBuffersDynamic { nullptr }
        , image2DViewOf3DSparse { nullptr }
        , defaultVertexAttributeValue { nullptr }
        , rgba4OpaqueBlackSwizzled { nullptr }
        , resolveSrgbFormatAppliesTransferFunction { nullptr }
        , resolveSrgbFormatSupportsTransferFunctionControl { nullptr }
        , allowCommandBufferQueryCopies { nullptr }
        , pipelineBinaryInternalCache { nullptr }
        , pipelineBinaryInternalCacheControl { nullptr }
        , pipelineBinaryPrefersInternalCache { nullptr }
        , pipelineBinaryPrecompiledInternalCache { nullptr }
        , pipelineBinaryCompressedData { nullptr }
        , pipelineExecutableInfo { nullptr }
        , shaderGroupHandleSize { nullptr }
        , maxRayRecursionDepth { nullptr }
        , maxShaderGroupStride { nullptr }
        , shaderGroupBaseAlignment { nullptr }
        , shaderGroupHandleCaptureReplaySize { nullptr }
        , maxRayDispatchInvocationCount { nullptr }
        , shaderGroupHandleAlignment { nullptr }
        , maxRayHitAttributeSize { nullptr }
        , robustStorageBufferAccessSizeAlignment { nullptr }
        , robustUniformBufferAccessSizeAlignment { nullptr } {

        _link();
    }

    device_properties_khr& operator=(const device_properties_khr& properties) {

        VkPhysicalDeviceAccelerationStructurePropertiesKHR::operator=(properties);
        VkPhysicalDeviceComputeShaderDerivativesPropertiesKHR::operator=(properties);
        VkPhysicalDeviceCooperativeMatrixPropertiesKHR::operator=(properties);
        VkPhysicalDeviceCopyMemoryIndirectPropertiesKHR::operator=(properties);
        VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR::operator=(properties);
        VkPhysicalDeviceFragmentShadingRatePropertiesKHR::operator=(properties);
        VkPhysicalDeviceLayeredApiPropertiesListKHR::operator=(properties);
        VkPhysicalDeviceLayeredApiVulkanPropertiesKHR::operator=(properties);
        VkPhysicalDeviceMaintenance7PropertiesKHR::operator=(properties);
        VkPhysicalDeviceMaintenance9PropertiesKHR::operator=(properties);
        VkPhysicalDeviceMaintenance10PropertiesKHR::operator=(properties);
        VkPhysicalDevicePerformanceQueryPropertiesKHR::operator=(properties);
        VkPhysicalDevicePipelineBinaryPropertiesKHR::operator=(properties);
        VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR::operator=(properties);
        VkPhysicalDeviceRayTracingPipelinePropertiesKHR::operator=(properties);
        VkPhysicalDeviceRobustness2PropertiesKHR::operator=(properties);

        _link();

        return *this;
    }

    ///
    /// \brief Chain an extension structure
    /// \param next
    void chain(void* next) {

        VkPhysicalDeviceRobustness2PropertiesKHR::pNext = next;
    }

    ///
    /// \brief Implicit casting for chaining
    operator void*() {

        return static_cast<VkPhysicalDeviceAccelerationStructurePropertiesKHR*>(this);
    }


// Helpers -------------------------------------------------------------------------------------------------------------
private:

    void _clear() {

        // Clear out the struct
        fennec::memset(this, 0, sizeof(*this));

        // Set the structure types
        VkPhysicalDeviceAccelerationStructurePropertiesKHR::sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ACCELERATION_STRUCTURE_PROPERTIES_KHR;
        VkPhysicalDeviceComputeShaderDerivativesPropertiesKHR::sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COMPUTE_SHADER_DERIVATIVES_PROPERTIES_KHR;
        VkPhysicalDeviceCooperativeMatrixPropertiesKHR::sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COOPERATIVE_MATRIX_PROPERTIES_KHR;
        VkPhysicalDeviceCopyMemoryIndirectPropertiesKHR::sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_COPY_MEMORY_INDIRECT_PROPERTIES_KHR;
        VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR::sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADER_BARYCENTRIC_PROPERTIES_KHR;
        VkPhysicalDeviceFragmentShadingRatePropertiesKHR::sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_PROPERTIES_KHR;
    }

    void _link() {

        // Link to Extension Structures
        maxGeometryCount                                           = &(VkPhysicalDeviceAccelerationStructurePropertiesKHR::maxGeometryCount);
        maxInstanceCount                                           = &(VkPhysicalDeviceAccelerationStructurePropertiesKHR::maxInstanceCount);
        maxPrimitiveCount                                          = &(VkPhysicalDeviceAccelerationStructurePropertiesKHR::maxPrimitiveCount);
        maxPerStageDescriptorAccelerationStructures                = &(VkPhysicalDeviceAccelerationStructurePropertiesKHR::maxPerStageDescriptorAccelerationStructures);
        maxPerStageDescriptorUpdateAfterBindAccelerationStructures = &(VkPhysicalDeviceAccelerationStructurePropertiesKHR::maxPerStageDescriptorUpdateAfterBindAccelerationStructures);
        maxDescriptorSetAccelerationStructures                     = &(VkPhysicalDeviceAccelerationStructurePropertiesKHR::maxDescriptorSetAccelerationStructures);
        maxDescriptorSetUpdateAfterBindAccelerationStructures      = &(VkPhysicalDeviceAccelerationStructurePropertiesKHR::maxDescriptorSetUpdateAfterBindAccelerationStructures);
        minAccelerationStructureScratchOffsetAlignment             = &(VkPhysicalDeviceAccelerationStructurePropertiesKHR::minAccelerationStructureScratchOffsetAlignment);
        meshAndTaskShaderDerivatives                               = &(VkPhysicalDeviceComputeShaderDerivativesPropertiesKHR::meshAndTaskShaderDerivatives);
        cooperativeMatrixSupportedStages                           = &(VkPhysicalDeviceCooperativeMatrixPropertiesKHR::cooperativeMatrixSupportedStages);
        supportedCopyQueues                                        = &(VkPhysicalDeviceCopyMemoryIndirectPropertiesKHR::supportedQueues);
        triStripVertexOrderIndependentOfProvokingVertex            = &(VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR::triStripVertexOrderIndependentOfProvokingVertex);
        minFragmentShadingRateAttachmentTexelSize                  = &(VkPhysicalDeviceFragmentShadingRatePropertiesKHR::minFragmentShadingRateAttachmentTexelSize);
        maxFragmentShadingRateAttachmentTexelSize                  = &(VkPhysicalDeviceFragmentShadingRatePropertiesKHR::maxFragmentShadingRateAttachmentTexelSize);
        maxFragmentShadingRateAttachmentTexelSizeAspectRatio       = &(VkPhysicalDeviceFragmentShadingRatePropertiesKHR::maxFragmentShadingRateAttachmentTexelSizeAspectRatio);
        primitiveFragmentShadingRateWithMultipleViewports          = &(VkPhysicalDeviceFragmentShadingRatePropertiesKHR::primitiveFragmentShadingRateWithMultipleViewports);
        layeredShadingRateAttachments                              = &(VkPhysicalDeviceFragmentShadingRatePropertiesKHR::layeredShadingRateAttachments);
        fragmentShadingRateNonTrivialCombinerOps                   = &(VkPhysicalDeviceFragmentShadingRatePropertiesKHR::fragmentShadingRateNonTrivialCombinerOps);
        maxFragmentSize                                            = &(VkPhysicalDeviceFragmentShadingRatePropertiesKHR::maxFragmentSize);
        maxFragmentSizeAspectRatio                                 = &(VkPhysicalDeviceFragmentShadingRatePropertiesKHR::maxFragmentSizeAspectRatio);
        maxFragmentShadingRateCoverageSamples                      = &(VkPhysicalDeviceFragmentShadingRatePropertiesKHR::maxFragmentShadingRateCoverageSamples);
        maxFragmentShadingRateRasterizationSamples                 = &(VkPhysicalDeviceFragmentShadingRatePropertiesKHR::maxFragmentShadingRateRasterizationSamples);
        fragmentShadingRateWithShaderDepthStencilWrites            = &(VkPhysicalDeviceFragmentShadingRatePropertiesKHR::fragmentShadingRateWithShaderDepthStencilWrites);
        fragmentShadingRateWithSampleMask                          = &(VkPhysicalDeviceFragmentShadingRatePropertiesKHR::fragmentShadingRateWithSampleMask);
        fragmentShadingRateWithShaderSampleMask                    = &(VkPhysicalDeviceFragmentShadingRatePropertiesKHR::fragmentShadingRateWithShaderSampleMask);
        fragmentShadingRateWithConservativeRasterization           = &(VkPhysicalDeviceFragmentShadingRatePropertiesKHR::fragmentShadingRateWithConservativeRasterization);
        fragmentShadingRateWithFragmentShaderInterlock             = &(VkPhysicalDeviceFragmentShadingRatePropertiesKHR::fragmentShadingRateWithFragmentShaderInterlock);
        fragmentShadingRateWithCustomSampleLocations               = &(VkPhysicalDeviceFragmentShadingRatePropertiesKHR::fragmentShadingRateWithCustomSampleLocations);
        fragmentShadingRateStrictMultiplyCombiner                  = &(VkPhysicalDeviceFragmentShadingRatePropertiesKHR::fragmentShadingRateStrictMultiplyCombiner);
        layeredApiCount                                            = &(VkPhysicalDeviceLayeredApiPropertiesListKHR::layeredApiCount);
        pLayeredApis                                               = &(VkPhysicalDeviceLayeredApiPropertiesListKHR::pLayeredApis);
        layerProperties                                            = &(VkPhysicalDeviceLayeredApiVulkanPropertiesKHR::properties);
        robustFragmentShadingRateAttachmentAccess                  = &(VkPhysicalDeviceMaintenance7PropertiesKHR::robustFragmentShadingRateAttachmentAccess);
        separateDepthStencilAttachmentAccess                       = &(VkPhysicalDeviceMaintenance7PropertiesKHR::separateDepthStencilAttachmentAccess);
        maxDescriptorSetTotalUniformBuffersDynamic                 = &(VkPhysicalDeviceMaintenance7PropertiesKHR::maxDescriptorSetTotalUniformBuffersDynamic);
        maxDescriptorSetTotalStorageBuffersDynamic                 = &(VkPhysicalDeviceMaintenance7PropertiesKHR::maxDescriptorSetTotalStorageBuffersDynamic);
        maxDescriptorSetTotalBuffersDynamic                        = &(VkPhysicalDeviceMaintenance7PropertiesKHR::maxDescriptorSetTotalBuffersDynamic);
        maxDescriptorSetUpdateAfterBindTotalUniformBuffersDynamic  = &(VkPhysicalDeviceMaintenance7PropertiesKHR::maxDescriptorSetUpdateAfterBindTotalUniformBuffersDynamic);
        maxDescriptorSetUpdateAfterBindTotalStorageBuffersDynamic  = &(VkPhysicalDeviceMaintenance7PropertiesKHR::maxDescriptorSetUpdateAfterBindTotalStorageBuffersDynamic);
        maxDescriptorSetUpdateAfterBindTotalBuffersDynamic         = &(VkPhysicalDeviceMaintenance7PropertiesKHR::maxDescriptorSetUpdateAfterBindTotalBuffersDynamic);
        image2DViewOf3DSparse                                      = &(VkPhysicalDeviceMaintenance9PropertiesKHR::image2DViewOf3DSparse);
        defaultVertexAttributeValue                                = &(VkPhysicalDeviceMaintenance9PropertiesKHR::defaultVertexAttributeValue);
        rgba4OpaqueBlackSwizzled                                   = &(VkPhysicalDeviceMaintenance10PropertiesKHR::rgba4OpaqueBlackSwizzled);
        resolveSrgbFormatAppliesTransferFunction                   = &(VkPhysicalDeviceMaintenance10PropertiesKHR::resolveSrgbFormatAppliesTransferFunction);
        resolveSrgbFormatSupportsTransferFunctionControl           = &(VkPhysicalDeviceMaintenance10PropertiesKHR::resolveSrgbFormatSupportsTransferFunctionControl);
        allowCommandBufferQueryCopies                              = &(VkPhysicalDevicePerformanceQueryPropertiesKHR::allowCommandBufferQueryCopies);
        pipelineBinaryInternalCache                                = &(VkPhysicalDevicePipelineBinaryPropertiesKHR::pipelineBinaryInternalCache);
        pipelineBinaryInternalCacheControl                         = &(VkPhysicalDevicePipelineBinaryPropertiesKHR::pipelineBinaryInternalCacheControl);
        pipelineBinaryPrefersInternalCache                         = &(VkPhysicalDevicePipelineBinaryPropertiesKHR::pipelineBinaryPrefersInternalCache);
        pipelineBinaryPrecompiledInternalCache                     = &(VkPhysicalDevicePipelineBinaryPropertiesKHR::pipelineBinaryPrecompiledInternalCache);
        pipelineBinaryCompressedData                               = &(VkPhysicalDevicePipelineBinaryPropertiesKHR::pipelineBinaryCompressedData);
        pipelineExecutableInfo                                     = &(VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR::pipelineExecutableInfo);
        shaderGroupHandleSize                                      = &(VkPhysicalDeviceRayTracingPipelinePropertiesKHR::shaderGroupHandleSize);
        maxRayRecursionDepth                                       = &(VkPhysicalDeviceRayTracingPipelinePropertiesKHR::maxRayRecursionDepth);
        maxShaderGroupStride                                       = &(VkPhysicalDeviceRayTracingPipelinePropertiesKHR::maxShaderGroupStride);
        shaderGroupBaseAlignment                                   = &(VkPhysicalDeviceRayTracingPipelinePropertiesKHR::shaderGroupBaseAlignment);
        shaderGroupHandleCaptureReplaySize                         = &(VkPhysicalDeviceRayTracingPipelinePropertiesKHR::shaderGroupHandleCaptureReplaySize);
        maxRayDispatchInvocationCount                              = &(VkPhysicalDeviceRayTracingPipelinePropertiesKHR::maxRayDispatchInvocationCount);
        shaderGroupHandleAlignment                                 = &(VkPhysicalDeviceRayTracingPipelinePropertiesKHR::shaderGroupHandleAlignment);
        maxRayHitAttributeSize                                     = &(VkPhysicalDeviceRayTracingPipelinePropertiesKHR::maxRayHitAttributeSize);
        robustStorageBufferAccessSizeAlignment                     = &(VkPhysicalDeviceRobustness2PropertiesKHR::robustStorageBufferAccessSizeAlignment);
        robustUniformBufferAccessSizeAlignment                     = &(VkPhysicalDeviceRobustness2PropertiesKHR::robustUniformBufferAccessSizeAlignment);

        // Daisy chain
        VkPhysicalDeviceAccelerationStructurePropertiesKHR::pNext      = static_cast<VkPhysicalDeviceComputeShaderDerivativesPropertiesKHR*>(this);
        VkPhysicalDeviceComputeShaderDerivativesPropertiesKHR::pNext   = static_cast<VkPhysicalDeviceCooperativeMatrixPropertiesKHR*>(this);
        VkPhysicalDeviceCooperativeMatrixPropertiesKHR::pNext          = static_cast<VkPhysicalDeviceCopyMemoryIndirectPropertiesKHR*>(this);
        VkPhysicalDeviceCopyMemoryIndirectPropertiesKHR::pNext         = static_cast<VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR*>(this);
        VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR::pNext  = static_cast<VkPhysicalDeviceFragmentShadingRatePropertiesKHR*>(this);
        VkPhysicalDeviceFragmentShadingRatePropertiesKHR::pNext        = static_cast<VkPhysicalDeviceLayeredApiPropertiesListKHR*>(this);
        VkPhysicalDeviceLayeredApiPropertiesListKHR::pNext             = static_cast<VkPhysicalDeviceLayeredApiVulkanPropertiesKHR*>(this);
        VkPhysicalDeviceLayeredApiVulkanPropertiesKHR::pNext           = static_cast<VkPhysicalDeviceMaintenance7PropertiesKHR*>(this);
        VkPhysicalDeviceMaintenance7PropertiesKHR::pNext               = static_cast<VkPhysicalDeviceMaintenance9PropertiesKHR*>(this);
        VkPhysicalDeviceMaintenance9PropertiesKHR::pNext               = static_cast<VkPhysicalDeviceMaintenance10PropertiesKHR*>(this);
        VkPhysicalDeviceMaintenance10PropertiesKHR::pNext              = static_cast<VkPhysicalDevicePerformanceQueryPropertiesKHR*>(this);
        VkPhysicalDevicePerformanceQueryPropertiesKHR::pNext           = static_cast<VkPhysicalDevicePipelineBinaryPropertiesKHR*>(this);
        VkPhysicalDevicePipelineBinaryPropertiesKHR::pNext             = static_cast<VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR*>(this);
        VkPhysicalDevicePipelineExecutablePropertiesFeaturesKHR::pNext = static_cast<VkPhysicalDeviceRayTracingPipelinePropertiesKHR*>(this);
        VkPhysicalDeviceRayTracingPipelinePropertiesKHR::pNext         = static_cast<VkPhysicalDeviceRobustness2PropertiesKHR*>(this);
        VkPhysicalDeviceRobustness2PropertiesKHR::pNext                = nullptr;
    }
};

///
/// \brief EXT Properties
struct device_properties_ext : private VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT,
                               private VkPhysicalDeviceConservativeRasterizationPropertiesEXT,
                               private VkPhysicalDeviceCustomBorderColorPropertiesEXT,
                               private VkPhysicalDeviceDescriptorBufferDensityMapPropertiesEXT,
                               private VkPhysicalDeviceDescriptorBufferPropertiesEXT,
                               private VkPhysicalDeviceDeviceGeneratedCommandsPropertiesEXT,
                               private VkPhysicalDeviceDiscardRectanglePropertiesEXT,
                               private VkPhysicalDeviceDrmPropertiesEXT,
                               private VkPhysicalDeviceExtendedDynamicState3PropertiesEXT,
                               private VkPhysicalDeviceExternalMemoryHostPropertiesEXT,
                               private VkPhysicalDeviceFragmentDensityMapPropertiesEXT,
                               private VkPhysicalDeviceFragmentDensityMap2PropertiesEXT,
                               private VkPhysicalDeviceFragmentDensityMapOffsetPropertiesEXT,
                               private VkPhysicalDeviceGraphicsPipelineLibraryPropertiesEXT,
                               private VkPhysicalDeviceLegacyVertexAttributesPropertiesEXT,
                               private VkPhysicalDeviceMapMemoryPlacedPropertiesEXT,
                               private VkPhysicalDeviceMemoryBudgetPropertiesEXT,
                               private VkPhysicalDeviceMemoryDecompressionPropertiesEXT,
                               private VkPhysicalDeviceMeshShaderPropertiesEXT,
                               private VkPhysicalDeviceMultiDrawPropertiesEXT,
                               private VkPhysicalDeviceNestedCommandBufferPropertiesEXT,
                               private VkPhysicalDeviceOpacityMicromapPropertiesEXT,
                               private VkPhysicalDevicePCIBusInfoPropertiesEXT,
                               private VkPhysicalDevicePipelinePropertiesFeaturesEXT,
                               private VkPhysicalDeviceProvokingVertexPropertiesEXT,
                               private VkPhysicalDeviceRayTracingInvocationReorderPropertiesEXT,
                               private VkPhysicalDeviceSampleLocationsPropertiesEXT,
                               private VkPhysicalDeviceShaderObjectPropertiesEXT,
                               private VkPhysicalDeviceShaderTileImagePropertiesEXT,
                               private VkPhysicalDeviceTransformFeedbackPropertiesEXT,
                               private VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT {

// Public References ---------------------------------------------------------------------------------------------------
public:

    /// \name Properties
    /// @{

    uint32_t*                             advancedBlendMaxColorAttachments;
    VkBool32*                             advancedBlendIndependentBlend;
    VkBool32*                             advancedBlendNonPremultipliedSrcColor;
    VkBool32*                             advancedBlendNonPremultipliedDstColor;
    VkBool32*                             advancedBlendCorrelatedOverlap;
    VkBool32*                             advancedBlendAllOperations;
    float*                                primitiveOverestimationSize;
    float*                                maxExtraPrimitiveOverestimationSize;
    float*                                extraPrimitiveOverestimationSizeGranularity;
    VkBool32*                             primitiveUnderestimation;
    VkBool32*                             conservativePointAndLineRasterization;
    VkBool32*                             degenerateTrianglesRasterized;
    VkBool32*                             degenerateLinesRasterized;
    VkBool32*                             fullyCoveredFragmentShaderInputVariable;
    VkBool32*                             conservativeRasterizationPostDepthCoverage;
    uint32_t*                             maxCustomBorderColorSamplers;
    size_t*                               combinedImageSamplerDensityMapDescriptorSize;
    VkBool32*                             combinedImageSamplerDescriptorSingleArray;
    VkBool32*                             bufferlessPushDescriptors;
    VkBool32*                             allowSamplerImageViewPostSubmitCreation;
    VkDeviceSize*                         descriptorBufferOffsetAlignment;
    uint32_t*                             maxDescriptorBufferBindings;
    uint32_t*                             maxResourceDescriptorBufferBindings;
    uint32_t*                             maxSamplerDescriptorBufferBindings;
    uint32_t*                             maxEmbeddedImmutableSamplerBindings;
    uint32_t*                             maxEmbeddedImmutableSamplers;
    size_t*                               bufferCaptureReplayDescriptorDataSize;
    size_t*                               imageCaptureReplayDescriptorDataSize;
    size_t*                               imageViewCaptureReplayDescriptorDataSize;
    size_t*                               samplerCaptureReplayDescriptorDataSize;
    size_t*                               accelerationStructureCaptureReplayDescriptorDataSize;
    size_t*                               samplerDescriptorSize;
    size_t*                               combinedImageSamplerDescriptorSize;
    size_t*                               sampledImageDescriptorSize;
    size_t*                               storageImageDescriptorSize;
    size_t*                               uniformTexelBufferDescriptorSize;
    size_t*                               robustUniformTexelBufferDescriptorSize;
    size_t*                               storageTexelBufferDescriptorSize;
    size_t*                               robustStorageTexelBufferDescriptorSize;
    size_t*                               uniformBufferDescriptorSize;
    size_t*                               robustUniformBufferDescriptorSize;
    size_t*                               storageBufferDescriptorSize;
    size_t*                               robustStorageBufferDescriptorSize;
    size_t*                               inputAttachmentDescriptorSize;
    size_t*                               accelerationStructureDescriptorSize;
    VkDeviceSize*                         maxSamplerDescriptorBufferRange;
    VkDeviceSize*                         maxResourceDescriptorBufferRange;
    VkDeviceSize*                         samplerDescriptorBufferAddressSpaceSize;
    VkDeviceSize*                         resourceDescriptorBufferAddressSpaceSize;
    VkDeviceSize*                         descriptorBufferAddressSpaceSize;
    uint32_t*                             maxIndirectPipelineCount;
    uint32_t*                             maxIndirectShaderObjectCount;
    uint32_t*                             maxIndirectSequenceCount;
    uint32_t*                             maxIndirectCommandsTokenCount;
    uint32_t*                             maxIndirectCommandsTokenOffset;
    uint32_t*                             maxIndirectCommandsIndirectStride;
    VkIndirectCommandsInputModeFlagsEXT*  supportedIndirectCommandsInputModes;
    VkShaderStageFlags*                   supportedIndirectCommandsShaderStages;
    VkShaderStageFlags*                   supportedIndirectCommandsShaderStagesPipelineBinding;
    VkShaderStageFlags*                   supportedIndirectCommandsShaderStagesShaderBinding;
    VkBool32*                             deviceGeneratedCommandsTransformFeedback;
    VkBool32*                             deviceGeneratedCommandsMultiDrawIndirectCount;
    uint32_t*                             maxDiscardRectangles;
    VkBool32*                             hasPrimary;
    VkBool32*                             hasRender;
    int64_t*                              primaryMajor;
    int64_t*                              primaryMinor;
    int64_t*                              renderMajor;
    int64_t*                              renderMinor;
    VkBool32*                             dynamicPrimitiveTopologyUnrestricted;
    VkDeviceSize*                         minImportedHostPointerAlignment;
    VkExtent2D*                           minFragmentDensityTexelSize;
    VkExtent2D*                           maxFragmentDensityTexelSize;
    VkBool32*                             fragmentDensityInvocations;
    VkBool32*                             subsampledLoads;
    VkBool32*                             subsampledCoarseReconstructionEarlyAccess;
    uint32_t*                             maxSubsampledArrayLayers;
    uint32_t*                             maxDescriptorSetSubsampledSamplers;
    VkExtent2D*                           fragmentDensityOffsetGranularity;
    VkBool32*                             graphicsPipelineLibraryFastLinking;
    VkBool32*                             graphicsPipelineLibraryIndependentInterpolationDecoration;
    VkBool32*                             nativeUnalignedPerformance;
    VkDeviceSize*                         minPlacedMemoryMapAlignment;
    VkDeviceSize                        (*heapBudget)[VK_MAX_MEMORY_HEAPS];
    VkDeviceSize                        (*heapUsage)[VK_MAX_MEMORY_HEAPS];
    VkMemoryDecompressionMethodFlagsEXT*  decompressionMethods;
    uint64_t*                             maxDecompressionIndirectCount;
    uint32_t*                             maxTaskWorkGroupTotalCount;
    uint32_t                            (*maxTaskWorkGroupCount)[3];
    uint32_t*                             maxTaskWorkGroupInvocations;
    uint32_t                            (*maxTaskWorkGroupSize)[3];
    uint32_t*                             maxTaskPayloadSize;
    uint32_t*                             maxTaskSharedMemorySize;
    uint32_t*                             maxTaskPayloadAndSharedMemorySize;
    uint32_t*                             maxMeshWorkGroupTotalCount;
    uint32_t                            (*maxMeshWorkGroupCount)[3];
    uint32_t*                             maxMeshWorkGroupInvocations;
    uint32_t                            (*maxMeshWorkGroupSize)[3];
    uint32_t*                             maxMeshSharedMemorySize;
    uint32_t*                             maxMeshPayloadAndSharedMemorySize;
    uint32_t*                             maxMeshOutputMemorySize;
    uint32_t*                             maxMeshPayloadAndOutputMemorySize;
    uint32_t*                             maxMeshOutputComponents;
    uint32_t*                             maxMeshOutputVertices;
    uint32_t*                             maxMeshOutputPrimitives;
    uint32_t*                             maxMeshOutputLayers;
    uint32_t*                             maxMeshMultiviewViewCount;
    uint32_t*                             meshOutputPerVertexGranularity;
    uint32_t*                             meshOutputPerPrimitiveGranularity;
    uint32_t*                             maxPreferredTaskWorkGroupInvocations;
    uint32_t*                             maxPreferredMeshWorkGroupInvocations;
    VkBool32*                             prefersLocalInvocationVertexOutput;
    VkBool32*                             prefersLocalInvocationPrimitiveOutput;
    VkBool32*                             prefersCompactVertexOutput;
    VkBool32*                             prefersCompactPrimitiveOutput;
    uint32_t*                             maxMultiDrawCount;
    uint32_t*                             maxCommandBufferNestingLevel;
    uint32_t*                             maxOpacity2StateSubdivisionLevel;
    uint32_t*                             maxOpacity4StateSubdivisionLevel;
    uint32_t*                             pciDomain;
    uint32_t*                             pciBus;
    uint32_t*                             pciDevice;
    uint32_t*                             pciFunction;
    VkBool32*                             pipelinePropertiesIdentifier;
    VkBool32*                             provokingVertexModePerPipeline;
    VkBool32*                             transformFeedbackPreservesTriangleFanProvokingVertex;
    VkRayTracingInvocationReorderModeEXT* rayTracingInvocationReorderReorderingHint;
    uint32_t*                             maxShaderBindingTableRecordIndex;
    VkSampleCountFlags*                   sampleLocationSampleCounts;
    VkExtent2D*                           maxSampleLocationGridSize;
    float                               (*sampleLocationCoordinateRange)[2];
    uint32_t*                             sampleLocationSubPixelBits;
    VkBool32*                             variableSampleLocations;
    uint8_t                             (*shaderBinaryUUID)[VK_UUID_SIZE];
    uint32_t*                             shaderBinaryVersion;
    VkBool32*                             shaderTileImageCoherentReadAccelerated;
    VkBool32*                             shaderTileImageReadSampleFromPixelRateInvocation;
    VkBool32*                             shaderTileImageReadFromHelperInvocation;
    uint32_t*                             maxTransformFeedbackStreams;
    uint32_t*                             maxTransformFeedbackBuffers;
    VkDeviceSize*                         maxTransformFeedbackBufferSize;
    uint32_t*                             maxTransformFeedbackStreamDataSize;
    uint32_t*                             maxTransformFeedbackBufferDataSize;
    uint32_t*                             maxTransformFeedbackBufferDataStride;
    VkBool32*                             transformFeedbackQueries;
    VkBool32*                             transformFeedbackStreamsLinesTriangles;
    VkBool32*                             transformFeedbackRasterizationStreamSelect;
    VkBool32*                             transformFeedbackDraw;
    uint32_t*                             maxVertexAttribDivisor;

    /// @}


// Methods -------------------------------------------------------------------------------------------------------------
public:

    device_properties_ext()
        : VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT { }
        , VkPhysicalDeviceConservativeRasterizationPropertiesEXT { }
        , VkPhysicalDeviceCustomBorderColorPropertiesEXT { }
        , VkPhysicalDeviceDescriptorBufferDensityMapPropertiesEXT { }
        , VkPhysicalDeviceDescriptorBufferPropertiesEXT { }
        , VkPhysicalDeviceDeviceGeneratedCommandsPropertiesEXT { }
        , VkPhysicalDeviceDiscardRectanglePropertiesEXT { }
        , VkPhysicalDeviceDrmPropertiesEXT { }
        , VkPhysicalDeviceExtendedDynamicState3PropertiesEXT { }
        , VkPhysicalDeviceExternalMemoryHostPropertiesEXT { }
        , VkPhysicalDeviceFragmentDensityMapPropertiesEXT { }
        , VkPhysicalDeviceFragmentDensityMap2PropertiesEXT { }
        , VkPhysicalDeviceFragmentDensityMapOffsetPropertiesEXT { }
        , VkPhysicalDeviceGraphicsPipelineLibraryPropertiesEXT { }
        , VkPhysicalDeviceLegacyVertexAttributesPropertiesEXT { }
        , VkPhysicalDeviceMapMemoryPlacedPropertiesEXT { }
        , VkPhysicalDeviceMemoryBudgetPropertiesEXT { }
        , VkPhysicalDeviceMemoryDecompressionPropertiesEXT { }
        , VkPhysicalDeviceMeshShaderPropertiesEXT { }
        , VkPhysicalDeviceMultiDrawPropertiesEXT { }
        , VkPhysicalDeviceNestedCommandBufferPropertiesEXT { }
        , VkPhysicalDeviceOpacityMicromapPropertiesEXT { }
        , VkPhysicalDevicePCIBusInfoPropertiesEXT { }
        , VkPhysicalDevicePipelinePropertiesFeaturesEXT { }
        , VkPhysicalDeviceProvokingVertexPropertiesEXT { }
        , VkPhysicalDeviceRayTracingInvocationReorderPropertiesEXT { }
        , VkPhysicalDeviceSampleLocationsPropertiesEXT { }
        , VkPhysicalDeviceShaderObjectPropertiesEXT { }
        , VkPhysicalDeviceShaderTileImagePropertiesEXT { }
        , VkPhysicalDeviceTransformFeedbackPropertiesEXT { }
        , VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT { }
        , advancedBlendMaxColorAttachments { nullptr }
        , advancedBlendIndependentBlend { nullptr }
        , advancedBlendNonPremultipliedSrcColor { nullptr }
        , advancedBlendNonPremultipliedDstColor { nullptr }
        , advancedBlendCorrelatedOverlap { nullptr }
        , advancedBlendAllOperations { nullptr }
        , primitiveOverestimationSize { nullptr }
        , maxExtraPrimitiveOverestimationSize { nullptr }
        , extraPrimitiveOverestimationSizeGranularity { nullptr }
        , primitiveUnderestimation { nullptr }
        , conservativePointAndLineRasterization { nullptr }
        , degenerateTrianglesRasterized { nullptr }
        , degenerateLinesRasterized { nullptr }
        , fullyCoveredFragmentShaderInputVariable { nullptr }
        , conservativeRasterizationPostDepthCoverage { nullptr }
        , maxCustomBorderColorSamplers { nullptr }
        , combinedImageSamplerDensityMapDescriptorSize { nullptr }
        , combinedImageSamplerDescriptorSingleArray { nullptr }
        , bufferlessPushDescriptors { nullptr }
        , allowSamplerImageViewPostSubmitCreation { nullptr }
        , descriptorBufferOffsetAlignment { nullptr }
        , maxDescriptorBufferBindings { nullptr }
        , maxResourceDescriptorBufferBindings { nullptr }
        , maxSamplerDescriptorBufferBindings { nullptr }
        , maxEmbeddedImmutableSamplerBindings { nullptr }
        , maxEmbeddedImmutableSamplers { nullptr }
        , bufferCaptureReplayDescriptorDataSize { nullptr }
        , imageCaptureReplayDescriptorDataSize { nullptr }
        , imageViewCaptureReplayDescriptorDataSize { nullptr }
        , samplerCaptureReplayDescriptorDataSize { nullptr }
        , accelerationStructureCaptureReplayDescriptorDataSize { nullptr }
        , samplerDescriptorSize { nullptr }
        , combinedImageSamplerDescriptorSize { nullptr }
        , sampledImageDescriptorSize { nullptr }
        , storageImageDescriptorSize { nullptr }
        , uniformTexelBufferDescriptorSize { nullptr }
        , robustUniformTexelBufferDescriptorSize { nullptr }
        , storageTexelBufferDescriptorSize { nullptr }
        , robustStorageTexelBufferDescriptorSize { nullptr }
        , uniformBufferDescriptorSize { nullptr }
        , robustUniformBufferDescriptorSize { nullptr }
        , storageBufferDescriptorSize { nullptr }
        , robustStorageBufferDescriptorSize { nullptr }
        , inputAttachmentDescriptorSize { nullptr }
        , accelerationStructureDescriptorSize { nullptr }
        , maxSamplerDescriptorBufferRange { nullptr }
        , maxResourceDescriptorBufferRange { nullptr }
        , samplerDescriptorBufferAddressSpaceSize { nullptr }
        , resourceDescriptorBufferAddressSpaceSize { nullptr }
        , descriptorBufferAddressSpaceSize { nullptr }
        , maxIndirectPipelineCount { nullptr }
        , maxIndirectShaderObjectCount { nullptr }
        , maxIndirectSequenceCount { nullptr }
        , maxIndirectCommandsTokenCount { nullptr }
        , maxIndirectCommandsTokenOffset { nullptr }
        , maxIndirectCommandsIndirectStride { nullptr }
        , supportedIndirectCommandsInputModes { nullptr }
        , supportedIndirectCommandsShaderStages { nullptr }
        , supportedIndirectCommandsShaderStagesPipelineBinding { nullptr }
        , supportedIndirectCommandsShaderStagesShaderBinding { nullptr }
        , deviceGeneratedCommandsTransformFeedback { nullptr }
        , deviceGeneratedCommandsMultiDrawIndirectCount { nullptr }
        , maxDiscardRectangles { nullptr }
        , hasPrimary { nullptr }
        , hasRender { nullptr }
        , primaryMajor { nullptr }
        , primaryMinor { nullptr }
        , renderMajor { nullptr }
        , renderMinor { nullptr }
        , dynamicPrimitiveTopologyUnrestricted { nullptr }
        , minImportedHostPointerAlignment { nullptr }
        , minFragmentDensityTexelSize { nullptr }
        , maxFragmentDensityTexelSize { nullptr }
        , fragmentDensityInvocations { nullptr }
        , subsampledLoads { nullptr }
        , subsampledCoarseReconstructionEarlyAccess { nullptr }
        , maxSubsampledArrayLayers { nullptr }
        , maxDescriptorSetSubsampledSamplers { nullptr }
        , fragmentDensityOffsetGranularity { nullptr }
        , graphicsPipelineLibraryFastLinking { nullptr }
        , graphicsPipelineLibraryIndependentInterpolationDecoration { nullptr }
        , nativeUnalignedPerformance { nullptr }
        , minPlacedMemoryMapAlignment { nullptr }
        , heapBudget { nullptr }
        , heapUsage { nullptr }
        , decompressionMethods { nullptr }
        , maxDecompressionIndirectCount { nullptr }
        , maxTaskWorkGroupTotalCount { nullptr }
        , maxTaskWorkGroupCount { nullptr }
        , maxTaskWorkGroupInvocations { nullptr }
        , maxTaskWorkGroupSize { nullptr }
        , maxTaskPayloadSize { nullptr }
        , maxTaskSharedMemorySize { nullptr }
        , maxTaskPayloadAndSharedMemorySize { nullptr }
        , maxMeshWorkGroupTotalCount { nullptr }
        , maxMeshWorkGroupCount { nullptr }
        , maxMeshWorkGroupInvocations { nullptr }
        , maxMeshWorkGroupSize { nullptr }
        , maxMeshSharedMemorySize { nullptr }
        , maxMeshPayloadAndSharedMemorySize { nullptr }
        , maxMeshOutputMemorySize { nullptr }
        , maxMeshPayloadAndOutputMemorySize { nullptr }
        , maxMeshOutputComponents { nullptr }
        , maxMeshOutputVertices { nullptr }
        , maxMeshOutputPrimitives { nullptr }
        , maxMeshOutputLayers { nullptr }
        , maxMeshMultiviewViewCount { nullptr }
        , meshOutputPerVertexGranularity { nullptr }
        , meshOutputPerPrimitiveGranularity { nullptr }
        , maxPreferredTaskWorkGroupInvocations { nullptr }
        , maxPreferredMeshWorkGroupInvocations { nullptr }
        , prefersLocalInvocationVertexOutput { nullptr }
        , prefersLocalInvocationPrimitiveOutput { nullptr }
        , prefersCompactVertexOutput { nullptr }
        , prefersCompactPrimitiveOutput { nullptr }
        , maxMultiDrawCount { nullptr }
        , maxCommandBufferNestingLevel { nullptr }
        , maxOpacity2StateSubdivisionLevel { nullptr }
        , maxOpacity4StateSubdivisionLevel { nullptr }
        , pciDomain { nullptr }
        , pciBus { nullptr }
        , pciDevice { nullptr }
        , pciFunction { nullptr }
        , pipelinePropertiesIdentifier { nullptr }
        , provokingVertexModePerPipeline { nullptr }
        , transformFeedbackPreservesTriangleFanProvokingVertex { nullptr }
        , rayTracingInvocationReorderReorderingHint { nullptr }
        , maxShaderBindingTableRecordIndex { nullptr }
        , sampleLocationSampleCounts { nullptr }
        , maxSampleLocationGridSize { nullptr }
        , sampleLocationCoordinateRange { nullptr }
        , sampleLocationSubPixelBits { nullptr }
        , variableSampleLocations { nullptr }
        , shaderBinaryUUID { nullptr }
        , shaderBinaryVersion { nullptr }
        , shaderTileImageCoherentReadAccelerated { nullptr }
        , shaderTileImageReadSampleFromPixelRateInvocation { nullptr }
        , shaderTileImageReadFromHelperInvocation { nullptr }
        , maxTransformFeedbackStreams { nullptr }
        , maxTransformFeedbackBuffers { nullptr }
        , maxTransformFeedbackBufferSize { nullptr }
        , maxTransformFeedbackStreamDataSize { nullptr }
        , maxTransformFeedbackBufferDataSize { nullptr }
        , maxTransformFeedbackBufferDataStride { nullptr }
        , transformFeedbackQueries { nullptr }
        , transformFeedbackStreamsLinesTriangles { nullptr }
        , transformFeedbackRasterizationStreamSelect { nullptr }
        , transformFeedbackDraw { nullptr }
        , maxVertexAttribDivisor { nullptr } {

        _clear();
        _link();
    }

    device_properties_ext(const device_properties_ext& properties)
        : VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT { properties }
        , VkPhysicalDeviceConservativeRasterizationPropertiesEXT { properties }
        , VkPhysicalDeviceCustomBorderColorPropertiesEXT { properties }
        , VkPhysicalDeviceDescriptorBufferDensityMapPropertiesEXT { properties }
        , VkPhysicalDeviceDescriptorBufferPropertiesEXT { properties }
        , VkPhysicalDeviceDeviceGeneratedCommandsPropertiesEXT { properties }
        , VkPhysicalDeviceDiscardRectanglePropertiesEXT { properties }
        , VkPhysicalDeviceDrmPropertiesEXT { properties }
        , VkPhysicalDeviceExtendedDynamicState3PropertiesEXT { properties }
        , VkPhysicalDeviceExternalMemoryHostPropertiesEXT { properties }
        , VkPhysicalDeviceFragmentDensityMapPropertiesEXT { properties }
        , VkPhysicalDeviceFragmentDensityMap2PropertiesEXT { properties }
        , VkPhysicalDeviceFragmentDensityMapOffsetPropertiesEXT { properties }
        , VkPhysicalDeviceGraphicsPipelineLibraryPropertiesEXT { properties }
        , VkPhysicalDeviceLegacyVertexAttributesPropertiesEXT { properties }
        , VkPhysicalDeviceMapMemoryPlacedPropertiesEXT { properties }
        , VkPhysicalDeviceMemoryBudgetPropertiesEXT { properties }
        , VkPhysicalDeviceMemoryDecompressionPropertiesEXT { properties }
        , VkPhysicalDeviceMeshShaderPropertiesEXT { properties }
        , VkPhysicalDeviceMultiDrawPropertiesEXT { properties }
        , VkPhysicalDeviceNestedCommandBufferPropertiesEXT { properties }
        , VkPhysicalDeviceOpacityMicromapPropertiesEXT { properties }
        , VkPhysicalDevicePCIBusInfoPropertiesEXT { properties }
        , VkPhysicalDevicePipelinePropertiesFeaturesEXT { properties }
        , VkPhysicalDeviceProvokingVertexPropertiesEXT { properties }
        , VkPhysicalDeviceRayTracingInvocationReorderPropertiesEXT { properties }
        , VkPhysicalDeviceSampleLocationsPropertiesEXT { properties }
        , VkPhysicalDeviceShaderObjectPropertiesEXT { properties }
        , VkPhysicalDeviceShaderTileImagePropertiesEXT { properties }
        , VkPhysicalDeviceTransformFeedbackPropertiesEXT { properties }
        , VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT { properties }
        , advancedBlendMaxColorAttachments { nullptr }
        , advancedBlendIndependentBlend { nullptr }
        , advancedBlendNonPremultipliedSrcColor { nullptr }
        , advancedBlendNonPremultipliedDstColor { nullptr }
        , advancedBlendCorrelatedOverlap { nullptr }
        , advancedBlendAllOperations { nullptr }
        , primitiveOverestimationSize { nullptr }
        , maxExtraPrimitiveOverestimationSize { nullptr }
        , extraPrimitiveOverestimationSizeGranularity { nullptr }
        , primitiveUnderestimation { nullptr }
        , conservativePointAndLineRasterization { nullptr }
        , degenerateTrianglesRasterized { nullptr }
        , degenerateLinesRasterized { nullptr }
        , fullyCoveredFragmentShaderInputVariable { nullptr }
        , conservativeRasterizationPostDepthCoverage { nullptr }
        , maxCustomBorderColorSamplers { nullptr }
        , combinedImageSamplerDensityMapDescriptorSize { nullptr }
        , combinedImageSamplerDescriptorSingleArray { nullptr }
        , bufferlessPushDescriptors { nullptr }
        , allowSamplerImageViewPostSubmitCreation { nullptr }
        , descriptorBufferOffsetAlignment { nullptr }
        , maxDescriptorBufferBindings { nullptr }
        , maxResourceDescriptorBufferBindings { nullptr }
        , maxSamplerDescriptorBufferBindings { nullptr }
        , maxEmbeddedImmutableSamplerBindings { nullptr }
        , maxEmbeddedImmutableSamplers { nullptr }
        , bufferCaptureReplayDescriptorDataSize { nullptr }
        , imageCaptureReplayDescriptorDataSize { nullptr }
        , imageViewCaptureReplayDescriptorDataSize { nullptr }
        , samplerCaptureReplayDescriptorDataSize { nullptr }
        , accelerationStructureCaptureReplayDescriptorDataSize { nullptr }
        , samplerDescriptorSize { nullptr }
        , combinedImageSamplerDescriptorSize { nullptr }
        , sampledImageDescriptorSize { nullptr }
        , storageImageDescriptorSize { nullptr }
        , uniformTexelBufferDescriptorSize { nullptr }
        , robustUniformTexelBufferDescriptorSize { nullptr }
        , storageTexelBufferDescriptorSize { nullptr }
        , robustStorageTexelBufferDescriptorSize { nullptr }
        , uniformBufferDescriptorSize { nullptr }
        , robustUniformBufferDescriptorSize { nullptr }
        , storageBufferDescriptorSize { nullptr }
        , robustStorageBufferDescriptorSize { nullptr }
        , inputAttachmentDescriptorSize { nullptr }
        , accelerationStructureDescriptorSize { nullptr }
        , maxSamplerDescriptorBufferRange { nullptr }
        , maxResourceDescriptorBufferRange { nullptr }
        , samplerDescriptorBufferAddressSpaceSize { nullptr }
        , resourceDescriptorBufferAddressSpaceSize { nullptr }
        , descriptorBufferAddressSpaceSize { nullptr }
        , maxIndirectPipelineCount { nullptr }
        , maxIndirectShaderObjectCount { nullptr }
        , maxIndirectSequenceCount { nullptr }
        , maxIndirectCommandsTokenCount { nullptr }
        , maxIndirectCommandsTokenOffset { nullptr }
        , maxIndirectCommandsIndirectStride { nullptr }
        , supportedIndirectCommandsInputModes { nullptr }
        , supportedIndirectCommandsShaderStages { nullptr }
        , supportedIndirectCommandsShaderStagesPipelineBinding { nullptr }
        , supportedIndirectCommandsShaderStagesShaderBinding { nullptr }
        , deviceGeneratedCommandsTransformFeedback { nullptr }
        , deviceGeneratedCommandsMultiDrawIndirectCount { nullptr }
        , maxDiscardRectangles { nullptr }
        , hasPrimary { nullptr }
        , hasRender { nullptr }
        , primaryMajor { nullptr }
        , primaryMinor { nullptr }
        , renderMajor { nullptr }
        , renderMinor { nullptr }
        , dynamicPrimitiveTopologyUnrestricted { nullptr }
        , minImportedHostPointerAlignment { nullptr }
        , minFragmentDensityTexelSize { nullptr }
        , maxFragmentDensityTexelSize { nullptr }
        , fragmentDensityInvocations { nullptr }
        , subsampledLoads { nullptr }
        , subsampledCoarseReconstructionEarlyAccess { nullptr }
        , maxSubsampledArrayLayers { nullptr }
        , maxDescriptorSetSubsampledSamplers { nullptr }
        , fragmentDensityOffsetGranularity { nullptr }
        , graphicsPipelineLibraryFastLinking { nullptr }
        , graphicsPipelineLibraryIndependentInterpolationDecoration { nullptr }
        , nativeUnalignedPerformance { nullptr }
        , minPlacedMemoryMapAlignment { nullptr }
        , heapBudget { nullptr }
        , heapUsage { nullptr }
        , decompressionMethods { nullptr }
        , maxDecompressionIndirectCount { nullptr }
        , maxTaskWorkGroupTotalCount { nullptr }
        , maxTaskWorkGroupCount { nullptr }
        , maxTaskWorkGroupInvocations { nullptr }
        , maxTaskWorkGroupSize { nullptr }
        , maxTaskPayloadSize { nullptr }
        , maxTaskSharedMemorySize { nullptr }
        , maxTaskPayloadAndSharedMemorySize { nullptr }
        , maxMeshWorkGroupTotalCount { nullptr }
        , maxMeshWorkGroupCount { nullptr }
        , maxMeshWorkGroupInvocations { nullptr }
        , maxMeshWorkGroupSize { nullptr }
        , maxMeshSharedMemorySize { nullptr }
        , maxMeshPayloadAndSharedMemorySize { nullptr }
        , maxMeshOutputMemorySize { nullptr }
        , maxMeshPayloadAndOutputMemorySize { nullptr }
        , maxMeshOutputComponents { nullptr }
        , maxMeshOutputVertices { nullptr }
        , maxMeshOutputPrimitives { nullptr }
        , maxMeshOutputLayers { nullptr }
        , maxMeshMultiviewViewCount { nullptr }
        , meshOutputPerVertexGranularity { nullptr }
        , meshOutputPerPrimitiveGranularity { nullptr }
        , maxPreferredTaskWorkGroupInvocations { nullptr }
        , maxPreferredMeshWorkGroupInvocations { nullptr }
        , prefersLocalInvocationVertexOutput { nullptr }
        , prefersLocalInvocationPrimitiveOutput { nullptr }
        , prefersCompactVertexOutput { nullptr }
        , prefersCompactPrimitiveOutput { nullptr }
        , maxMultiDrawCount { nullptr }
        , maxCommandBufferNestingLevel { nullptr }
        , maxOpacity2StateSubdivisionLevel { nullptr }
        , maxOpacity4StateSubdivisionLevel { nullptr }
        , pciDomain { nullptr }
        , pciBus { nullptr }
        , pciDevice { nullptr }
        , pciFunction { nullptr }
        , pipelinePropertiesIdentifier { nullptr }
        , provokingVertexModePerPipeline { nullptr }
        , transformFeedbackPreservesTriangleFanProvokingVertex { nullptr }
        , rayTracingInvocationReorderReorderingHint { nullptr }
        , maxShaderBindingTableRecordIndex { nullptr }
        , sampleLocationSampleCounts { nullptr }
        , maxSampleLocationGridSize { nullptr }
        , sampleLocationCoordinateRange { nullptr }
        , sampleLocationSubPixelBits { nullptr }
        , variableSampleLocations { nullptr }
        , shaderBinaryUUID { nullptr }
        , shaderBinaryVersion { nullptr }
        , shaderTileImageCoherentReadAccelerated { nullptr }
        , shaderTileImageReadSampleFromPixelRateInvocation { nullptr }
        , shaderTileImageReadFromHelperInvocation { nullptr }
        , maxTransformFeedbackStreams { nullptr }
        , maxTransformFeedbackBuffers { nullptr }
        , maxTransformFeedbackBufferSize { nullptr }
        , maxTransformFeedbackStreamDataSize { nullptr }
        , maxTransformFeedbackBufferDataSize { nullptr }
        , maxTransformFeedbackBufferDataStride { nullptr }
        , transformFeedbackQueries { nullptr }
        , transformFeedbackStreamsLinesTriangles { nullptr }
        , transformFeedbackRasterizationStreamSelect { nullptr }
        , transformFeedbackDraw { nullptr }
        , maxVertexAttribDivisor { nullptr } {

        _link();
    }

    device_properties_ext& operator=(const device_properties_ext& properties) {
        if (&properties == this) {
            return *this;
        }

        VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT::operator=(properties);
        VkPhysicalDeviceConservativeRasterizationPropertiesEXT::operator=(properties);
        VkPhysicalDeviceCustomBorderColorPropertiesEXT::operator=(properties);
        VkPhysicalDeviceDescriptorBufferDensityMapPropertiesEXT::operator=(properties);
        VkPhysicalDeviceDescriptorBufferPropertiesEXT::operator=(properties);
        VkPhysicalDeviceDeviceGeneratedCommandsPropertiesEXT::operator=(properties);
        VkPhysicalDeviceDiscardRectanglePropertiesEXT::operator=(properties);
        VkPhysicalDeviceDrmPropertiesEXT::operator=(properties);
        VkPhysicalDeviceExtendedDynamicState3PropertiesEXT::operator=(properties);
        VkPhysicalDeviceExternalMemoryHostPropertiesEXT::operator=(properties);
        VkPhysicalDeviceFragmentDensityMapPropertiesEXT::operator=(properties);
        VkPhysicalDeviceFragmentDensityMap2PropertiesEXT::operator=(properties);
        VkPhysicalDeviceFragmentDensityMapOffsetPropertiesEXT::operator=(properties);
        VkPhysicalDeviceGraphicsPipelineLibraryPropertiesEXT::operator=(properties);
        VkPhysicalDeviceLegacyVertexAttributesPropertiesEXT::operator=(properties);
        VkPhysicalDeviceMapMemoryPlacedPropertiesEXT::operator=(properties);
        VkPhysicalDeviceMemoryBudgetPropertiesEXT::operator=(properties);
        VkPhysicalDeviceMemoryDecompressionPropertiesEXT::operator=(properties);
        VkPhysicalDeviceMeshShaderPropertiesEXT::operator=(properties);
        VkPhysicalDeviceMultiDrawPropertiesEXT::operator=(properties);
        VkPhysicalDeviceNestedCommandBufferPropertiesEXT::operator=(properties);
        VkPhysicalDeviceOpacityMicromapPropertiesEXT::operator=(properties);
        VkPhysicalDevicePCIBusInfoPropertiesEXT::operator=(properties);
        VkPhysicalDevicePipelinePropertiesFeaturesEXT::operator=(properties);
        VkPhysicalDeviceProvokingVertexPropertiesEXT::operator=(properties);
        VkPhysicalDeviceRayTracingInvocationReorderPropertiesEXT::operator=(properties);
        VkPhysicalDeviceSampleLocationsPropertiesEXT::operator=(properties);
        VkPhysicalDeviceShaderObjectPropertiesEXT::operator=(properties);
        VkPhysicalDeviceShaderTileImagePropertiesEXT::operator=(properties);
        VkPhysicalDeviceTransformFeedbackPropertiesEXT::operator=(properties);
        VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT::operator=(properties);

        _link();

        return *this;
    }


// Helpers -------------------------------------------------------------------------------------------------------------
private:

    void _clear() {

        // Clear out the structure
        fennec::memset(this, 0, sizeof(*this));

        // Set the structure types
        VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT::sType      = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BLEND_OPERATION_ADVANCED_PROPERTIES_EXT;
        VkPhysicalDeviceConservativeRasterizationPropertiesEXT::sType   = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CONSERVATIVE_RASTERIZATION_PROPERTIES_EXT;
        VkPhysicalDeviceCustomBorderColorPropertiesEXT::sType           = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_CUSTOM_BORDER_COLOR_PROPERTIES_EXT;
        VkPhysicalDeviceDescriptorBufferDensityMapPropertiesEXT::sType  = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_DENSITY_MAP_PROPERTIES_EXT;
        VkPhysicalDeviceDescriptorBufferPropertiesEXT::sType            = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_BUFFER_PROPERTIES_EXT;
        VkPhysicalDeviceDeviceGeneratedCommandsPropertiesEXT::sType     = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEVICE_GENERATED_COMMANDS_PROPERTIES_EXT;
        VkPhysicalDeviceDiscardRectanglePropertiesEXT::sType            = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DISCARD_RECTANGLE_PROPERTIES_EXT;
        VkPhysicalDeviceDrmPropertiesEXT::sType                         = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRM_PROPERTIES_EXT;
        VkPhysicalDeviceExtendedDynamicState3PropertiesEXT::sType       = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTENDED_DYNAMIC_STATE_3_PROPERTIES_EXT;
        VkPhysicalDeviceExternalMemoryHostPropertiesEXT::sType          = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_EXTERNAL_MEMORY_HOST_PROPERTIES_EXT;
        VkPhysicalDeviceFragmentDensityMapPropertiesEXT::sType          = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_PROPERTIES_EXT;
        VkPhysicalDeviceFragmentDensityMap2PropertiesEXT::sType         = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_2_PROPERTIES_EXT;
        VkPhysicalDeviceFragmentDensityMapOffsetPropertiesEXT::sType    = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_OFFSET_PROPERTIES_EXT;
        VkPhysicalDeviceGraphicsPipelineLibraryPropertiesEXT::sType     = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GRAPHICS_PIPELINE_LIBRARY_PROPERTIES_EXT;
        VkPhysicalDeviceLegacyVertexAttributesPropertiesEXT::sType      = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LEGACY_VERTEX_ATTRIBUTES_PROPERTIES_EXT;
        VkPhysicalDeviceMapMemoryPlacedPropertiesEXT::sType             = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAP_MEMORY_PLACED_PROPERTIES_EXT;
        VkPhysicalDeviceMemoryBudgetPropertiesEXT::sType                = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT;
        VkPhysicalDeviceMemoryDecompressionPropertiesEXT::sType         = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_DECOMPRESSION_PROPERTIES_EXT;
        VkPhysicalDeviceMeshShaderPropertiesEXT::sType                  = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MESH_SHADER_PROPERTIES_EXT;
        VkPhysicalDeviceMultiDrawPropertiesEXT::sType                   = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_PROPERTIES_EXT;
        VkPhysicalDeviceNestedCommandBufferPropertiesEXT::sType         = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_NESTED_COMMAND_BUFFER_PROPERTIES_EXT;
        VkPhysicalDeviceOpacityMicromapPropertiesEXT::sType             = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_OPACITY_MICROMAP_PROPERTIES_EXT;
        VkPhysicalDevicePCIBusInfoPropertiesEXT::sType                  = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PCI_BUS_INFO_PROPERTIES_EXT;
        VkPhysicalDevicePipelinePropertiesFeaturesEXT::sType            = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PIPELINE_PROPERTIES_FEATURES_EXT;
        VkPhysicalDeviceProvokingVertexPropertiesEXT::sType             = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROVOKING_VERTEX_PROPERTIES_EXT;
        VkPhysicalDeviceRayTracingInvocationReorderPropertiesEXT::sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_RAY_TRACING_INVOCATION_REORDER_PROPERTIES_EXT;
        VkPhysicalDeviceSampleLocationsPropertiesEXT::sType             = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLE_LOCATIONS_PROPERTIES_EXT;
        VkPhysicalDeviceShaderObjectPropertiesEXT::sType                = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_OBJECT_PROPERTIES_EXT;
        VkPhysicalDeviceShaderTileImagePropertiesEXT::sType             = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADER_TILE_IMAGE_PROPERTIES_EXT;
        VkPhysicalDeviceTransformFeedbackPropertiesEXT::sType           = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT;
        VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT::sType      = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_PROPERTIES_EXT;
    }

    void _link() {

        // Link to extension structures
        advancedBlendMaxColorAttachments                          = &(VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT::advancedBlendMaxColorAttachments);
        advancedBlendIndependentBlend                             = &(VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT::advancedBlendIndependentBlend);
        advancedBlendNonPremultipliedSrcColor                     = &(VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT::advancedBlendNonPremultipliedSrcColor);
        advancedBlendNonPremultipliedDstColor                     = &(VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT::advancedBlendNonPremultipliedDstColor);
        advancedBlendCorrelatedOverlap                            = &(VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT::advancedBlendCorrelatedOverlap);
        advancedBlendAllOperations                                = &(VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT::advancedBlendAllOperations);
        primitiveOverestimationSize                               = &(VkPhysicalDeviceConservativeRasterizationPropertiesEXT::primitiveOverestimationSize);
        maxExtraPrimitiveOverestimationSize                       = &(VkPhysicalDeviceConservativeRasterizationPropertiesEXT::maxExtraPrimitiveOverestimationSize);
        extraPrimitiveOverestimationSizeGranularity               = &(VkPhysicalDeviceConservativeRasterizationPropertiesEXT::extraPrimitiveOverestimationSizeGranularity);
        primitiveUnderestimation                                  = &(VkPhysicalDeviceConservativeRasterizationPropertiesEXT::primitiveUnderestimation);
        conservativePointAndLineRasterization                     = &(VkPhysicalDeviceConservativeRasterizationPropertiesEXT::conservativePointAndLineRasterization);
        degenerateTrianglesRasterized                             = &(VkPhysicalDeviceConservativeRasterizationPropertiesEXT::degenerateTrianglesRasterized);
        degenerateLinesRasterized                                 = &(VkPhysicalDeviceConservativeRasterizationPropertiesEXT::degenerateLinesRasterized);
        fullyCoveredFragmentShaderInputVariable                   = &(VkPhysicalDeviceConservativeRasterizationPropertiesEXT::fullyCoveredFragmentShaderInputVariable);
        conservativeRasterizationPostDepthCoverage                = &(VkPhysicalDeviceConservativeRasterizationPropertiesEXT::conservativeRasterizationPostDepthCoverage);
        maxCustomBorderColorSamplers                              = &(VkPhysicalDeviceCustomBorderColorPropertiesEXT::maxCustomBorderColorSamplers);
        combinedImageSamplerDensityMapDescriptorSize              = &(VkPhysicalDeviceDescriptorBufferDensityMapPropertiesEXT::combinedImageSamplerDensityMapDescriptorSize);
        combinedImageSamplerDescriptorSingleArray                 = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::combinedImageSamplerDescriptorSingleArray);
        bufferlessPushDescriptors                                 = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::bufferlessPushDescriptors);
        allowSamplerImageViewPostSubmitCreation                   = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::allowSamplerImageViewPostSubmitCreation);
        descriptorBufferOffsetAlignment                           = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::descriptorBufferOffsetAlignment);
        maxDescriptorBufferBindings                               = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::maxDescriptorBufferBindings);
        maxResourceDescriptorBufferBindings                       = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::maxResourceDescriptorBufferBindings);
        maxSamplerDescriptorBufferBindings                        = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::maxSamplerDescriptorBufferBindings);
        maxEmbeddedImmutableSamplerBindings                       = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::maxEmbeddedImmutableSamplerBindings);
        maxEmbeddedImmutableSamplers                              = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::maxEmbeddedImmutableSamplers);
        bufferCaptureReplayDescriptorDataSize                     = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::bufferCaptureReplayDescriptorDataSize);
        imageCaptureReplayDescriptorDataSize                      = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::imageCaptureReplayDescriptorDataSize);
        imageViewCaptureReplayDescriptorDataSize                  = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::imageViewCaptureReplayDescriptorDataSize);
        samplerCaptureReplayDescriptorDataSize                    = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::samplerCaptureReplayDescriptorDataSize);
        accelerationStructureCaptureReplayDescriptorDataSize      = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::accelerationStructureCaptureReplayDescriptorDataSize);
        samplerDescriptorSize                                     = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::samplerDescriptorSize);
        combinedImageSamplerDescriptorSize                        = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::combinedImageSamplerDescriptorSize);
        sampledImageDescriptorSize                                = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::sampledImageDescriptorSize);
        storageImageDescriptorSize                                = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::storageImageDescriptorSize);
        uniformTexelBufferDescriptorSize                          = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::uniformTexelBufferDescriptorSize);
        robustUniformTexelBufferDescriptorSize                    = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::robustUniformTexelBufferDescriptorSize);
        storageTexelBufferDescriptorSize                          = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::storageTexelBufferDescriptorSize);
        robustStorageTexelBufferDescriptorSize                    = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::robustStorageTexelBufferDescriptorSize);
        uniformBufferDescriptorSize                               = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::uniformBufferDescriptorSize);
        robustUniformBufferDescriptorSize                         = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::robustUniformBufferDescriptorSize);
        storageBufferDescriptorSize                               = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::storageBufferDescriptorSize);
        robustStorageBufferDescriptorSize                         = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::robustStorageBufferDescriptorSize);
        inputAttachmentDescriptorSize                             = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::inputAttachmentDescriptorSize);
        accelerationStructureDescriptorSize                       = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::accelerationStructureDescriptorSize);
        maxSamplerDescriptorBufferRange                           = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::maxSamplerDescriptorBufferRange);
        maxResourceDescriptorBufferRange                          = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::maxResourceDescriptorBufferRange);
        samplerDescriptorBufferAddressSpaceSize                   = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::samplerDescriptorBufferAddressSpaceSize);
        resourceDescriptorBufferAddressSpaceSize                  = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::resourceDescriptorBufferAddressSpaceSize);
        descriptorBufferAddressSpaceSize                          = &(VkPhysicalDeviceDescriptorBufferPropertiesEXT::descriptorBufferAddressSpaceSize);
        maxIndirectPipelineCount                                  = &(VkPhysicalDeviceDeviceGeneratedCommandsPropertiesEXT::maxIndirectPipelineCount);
        maxIndirectShaderObjectCount                              = &(VkPhysicalDeviceDeviceGeneratedCommandsPropertiesEXT::maxIndirectShaderObjectCount);
        maxIndirectSequenceCount                                  = &(VkPhysicalDeviceDeviceGeneratedCommandsPropertiesEXT::maxIndirectSequenceCount);
        maxIndirectCommandsTokenCount                             = &(VkPhysicalDeviceDeviceGeneratedCommandsPropertiesEXT::maxIndirectCommandsTokenCount);
        maxIndirectCommandsTokenOffset                            = &(VkPhysicalDeviceDeviceGeneratedCommandsPropertiesEXT::maxIndirectCommandsTokenOffset);
        maxIndirectCommandsIndirectStride                         = &(VkPhysicalDeviceDeviceGeneratedCommandsPropertiesEXT::maxIndirectCommandsIndirectStride);
        supportedIndirectCommandsInputModes                       = &(VkPhysicalDeviceDeviceGeneratedCommandsPropertiesEXT::supportedIndirectCommandsInputModes);
        supportedIndirectCommandsShaderStages                     = &(VkPhysicalDeviceDeviceGeneratedCommandsPropertiesEXT::supportedIndirectCommandsShaderStages);
        supportedIndirectCommandsShaderStagesPipelineBinding      = &(VkPhysicalDeviceDeviceGeneratedCommandsPropertiesEXT::supportedIndirectCommandsShaderStagesPipelineBinding);
        supportedIndirectCommandsShaderStagesShaderBinding        = &(VkPhysicalDeviceDeviceGeneratedCommandsPropertiesEXT::supportedIndirectCommandsShaderStagesShaderBinding);
        deviceGeneratedCommandsTransformFeedback                  = &(VkPhysicalDeviceDeviceGeneratedCommandsPropertiesEXT::deviceGeneratedCommandsTransformFeedback);
        deviceGeneratedCommandsMultiDrawIndirectCount             = &(VkPhysicalDeviceDeviceGeneratedCommandsPropertiesEXT::deviceGeneratedCommandsMultiDrawIndirectCount);
        maxDiscardRectangles                                      = &(VkPhysicalDeviceDiscardRectanglePropertiesEXT::maxDiscardRectangles);
        hasPrimary                                                = &(VkPhysicalDeviceDrmPropertiesEXT::hasPrimary);
        hasRender                                                 = &(VkPhysicalDeviceDrmPropertiesEXT::hasRender);
        primaryMajor                                              = &(VkPhysicalDeviceDrmPropertiesEXT::primaryMajor);
        primaryMinor                                              = &(VkPhysicalDeviceDrmPropertiesEXT::primaryMinor);
        renderMajor                                               = &(VkPhysicalDeviceDrmPropertiesEXT::renderMajor);
        renderMinor                                               = &(VkPhysicalDeviceDrmPropertiesEXT::renderMinor);
        dynamicPrimitiveTopologyUnrestricted                      = &(VkPhysicalDeviceExtendedDynamicState3PropertiesEXT::dynamicPrimitiveTopologyUnrestricted);
        minImportedHostPointerAlignment                           = &(VkPhysicalDeviceExternalMemoryHostPropertiesEXT::minImportedHostPointerAlignment);
        minFragmentDensityTexelSize                               = &(VkPhysicalDeviceFragmentDensityMapPropertiesEXT::minFragmentDensityTexelSize);
        maxFragmentDensityTexelSize                               = &(VkPhysicalDeviceFragmentDensityMapPropertiesEXT::maxFragmentDensityTexelSize);
        fragmentDensityInvocations                                = &(VkPhysicalDeviceFragmentDensityMapPropertiesEXT::fragmentDensityInvocations);
        subsampledLoads                                           = &(VkPhysicalDeviceFragmentDensityMap2PropertiesEXT::subsampledLoads);
        subsampledCoarseReconstructionEarlyAccess                 = &(VkPhysicalDeviceFragmentDensityMap2PropertiesEXT::subsampledCoarseReconstructionEarlyAccess);
        maxSubsampledArrayLayers                                  = &(VkPhysicalDeviceFragmentDensityMap2PropertiesEXT::maxSubsampledArrayLayers);
        maxDescriptorSetSubsampledSamplers                        = &(VkPhysicalDeviceFragmentDensityMap2PropertiesEXT::maxDescriptorSetSubsampledSamplers);
        fragmentDensityOffsetGranularity                          = &(VkPhysicalDeviceFragmentDensityMapOffsetPropertiesEXT::fragmentDensityOffsetGranularity);
        graphicsPipelineLibraryFastLinking                        = &(VkPhysicalDeviceGraphicsPipelineLibraryPropertiesEXT::graphicsPipelineLibraryFastLinking);
        graphicsPipelineLibraryIndependentInterpolationDecoration = &(VkPhysicalDeviceGraphicsPipelineLibraryPropertiesEXT::graphicsPipelineLibraryIndependentInterpolationDecoration);
        nativeUnalignedPerformance                                = &(VkPhysicalDeviceLegacyVertexAttributesPropertiesEXT::nativeUnalignedPerformance);
        minPlacedMemoryMapAlignment                               = &(VkPhysicalDeviceMapMemoryPlacedPropertiesEXT::minPlacedMemoryMapAlignment);
        heapBudget                                                = &(VkPhysicalDeviceMemoryBudgetPropertiesEXT::heapBudget);
        heapUsage                                                 = &(VkPhysicalDeviceMemoryBudgetPropertiesEXT::heapUsage);
        decompressionMethods                                      = &(VkPhysicalDeviceMemoryDecompressionPropertiesEXT::decompressionMethods);
        maxDecompressionIndirectCount                             = &(VkPhysicalDeviceMemoryDecompressionPropertiesEXT::maxDecompressionIndirectCount);
        maxTaskWorkGroupTotalCount                                = &(VkPhysicalDeviceMeshShaderPropertiesEXT::maxTaskWorkGroupTotalCount);
        maxTaskWorkGroupCount                                     = &(VkPhysicalDeviceMeshShaderPropertiesEXT::maxTaskWorkGroupCount);
        maxTaskWorkGroupInvocations                               = &(VkPhysicalDeviceMeshShaderPropertiesEXT::maxTaskWorkGroupInvocations);
        maxTaskWorkGroupSize                                      = &(VkPhysicalDeviceMeshShaderPropertiesEXT::maxTaskWorkGroupSize);
        maxTaskPayloadSize                                        = &(VkPhysicalDeviceMeshShaderPropertiesEXT::maxTaskPayloadSize);
        maxTaskSharedMemorySize                                   = &(VkPhysicalDeviceMeshShaderPropertiesEXT::maxTaskSharedMemorySize);
        maxTaskPayloadAndSharedMemorySize                         = &(VkPhysicalDeviceMeshShaderPropertiesEXT::maxTaskPayloadAndSharedMemorySize);
        maxMeshWorkGroupTotalCount                                = &(VkPhysicalDeviceMeshShaderPropertiesEXT::maxMeshWorkGroupTotalCount);
        maxMeshWorkGroupCount                                     = &(VkPhysicalDeviceMeshShaderPropertiesEXT::maxMeshWorkGroupCount);
        maxMeshWorkGroupInvocations                               = &(VkPhysicalDeviceMeshShaderPropertiesEXT::maxMeshWorkGroupInvocations);
        maxMeshWorkGroupSize                                      = &(VkPhysicalDeviceMeshShaderPropertiesEXT::maxMeshWorkGroupSize);
        maxMeshSharedMemorySize                                   = &(VkPhysicalDeviceMeshShaderPropertiesEXT::maxMeshSharedMemorySize);
        maxMeshPayloadAndSharedMemorySize                         = &(VkPhysicalDeviceMeshShaderPropertiesEXT::maxMeshPayloadAndSharedMemorySize);
        maxMeshOutputMemorySize                                   = &(VkPhysicalDeviceMeshShaderPropertiesEXT::maxMeshOutputMemorySize);
        maxMeshPayloadAndOutputMemorySize                         = &(VkPhysicalDeviceMeshShaderPropertiesEXT::maxMeshPayloadAndOutputMemorySize);
        maxMeshOutputComponents                                   = &(VkPhysicalDeviceMeshShaderPropertiesEXT::maxMeshOutputComponents);
        maxMeshOutputVertices                                     = &(VkPhysicalDeviceMeshShaderPropertiesEXT::maxMeshOutputVertices);
        maxMeshOutputPrimitives                                   = &(VkPhysicalDeviceMeshShaderPropertiesEXT::maxMeshOutputPrimitives);
        maxMeshOutputLayers                                       = &(VkPhysicalDeviceMeshShaderPropertiesEXT::maxMeshOutputLayers);
        maxMeshMultiviewViewCount                                 = &(VkPhysicalDeviceMeshShaderPropertiesEXT::maxMeshMultiviewViewCount);
        meshOutputPerVertexGranularity                            = &(VkPhysicalDeviceMeshShaderPropertiesEXT::meshOutputPerVertexGranularity);
        meshOutputPerPrimitiveGranularity                         = &(VkPhysicalDeviceMeshShaderPropertiesEXT::meshOutputPerPrimitiveGranularity);
        maxPreferredTaskWorkGroupInvocations                      = &(VkPhysicalDeviceMeshShaderPropertiesEXT::maxPreferredTaskWorkGroupInvocations);
        maxPreferredMeshWorkGroupInvocations                      = &(VkPhysicalDeviceMeshShaderPropertiesEXT::maxPreferredMeshWorkGroupInvocations);
        prefersLocalInvocationVertexOutput                        = &(VkPhysicalDeviceMeshShaderPropertiesEXT::prefersLocalInvocationVertexOutput);
        prefersLocalInvocationPrimitiveOutput                     = &(VkPhysicalDeviceMeshShaderPropertiesEXT::prefersLocalInvocationPrimitiveOutput);
        prefersCompactVertexOutput                                = &(VkPhysicalDeviceMeshShaderPropertiesEXT::prefersCompactVertexOutput);
        prefersCompactPrimitiveOutput                             = &(VkPhysicalDeviceMeshShaderPropertiesEXT::prefersCompactPrimitiveOutput);
        maxMultiDrawCount                                         = &(VkPhysicalDeviceMultiDrawPropertiesEXT::maxMultiDrawCount);
        maxCommandBufferNestingLevel                              = &(VkPhysicalDeviceNestedCommandBufferPropertiesEXT::maxCommandBufferNestingLevel);
        maxOpacity2StateSubdivisionLevel                          = &(VkPhysicalDeviceOpacityMicromapPropertiesEXT::maxOpacity2StateSubdivisionLevel);
        maxOpacity4StateSubdivisionLevel                          = &(VkPhysicalDeviceOpacityMicromapPropertiesEXT::maxOpacity4StateSubdivisionLevel);
        pciDomain                                                 = &(VkPhysicalDevicePCIBusInfoPropertiesEXT::pciDomain);
        pciBus                                                    = &(VkPhysicalDevicePCIBusInfoPropertiesEXT::pciBus);
        pciDevice                                                 = &(VkPhysicalDevicePCIBusInfoPropertiesEXT::pciDevice);
        pciFunction                                               = &(VkPhysicalDevicePCIBusInfoPropertiesEXT::pciFunction);
        pipelinePropertiesIdentifier                              = &(VkPhysicalDevicePipelinePropertiesFeaturesEXT::pipelinePropertiesIdentifier);
        provokingVertexModePerPipeline                            = &(VkPhysicalDeviceProvokingVertexPropertiesEXT::provokingVertexModePerPipeline);
        transformFeedbackPreservesTriangleFanProvokingVertex      = &(VkPhysicalDeviceProvokingVertexPropertiesEXT::transformFeedbackPreservesTriangleFanProvokingVertex);
        rayTracingInvocationReorderReorderingHint                 = &(VkPhysicalDeviceRayTracingInvocationReorderPropertiesEXT::rayTracingInvocationReorderReorderingHint);
        maxShaderBindingTableRecordIndex                          = &(VkPhysicalDeviceRayTracingInvocationReorderPropertiesEXT::maxShaderBindingTableRecordIndex);
        sampleLocationSampleCounts                                = &(VkPhysicalDeviceSampleLocationsPropertiesEXT::sampleLocationSampleCounts);
        maxSampleLocationGridSize                                 = &(VkPhysicalDeviceSampleLocationsPropertiesEXT::maxSampleLocationGridSize);
        sampleLocationCoordinateRange                             = &(VkPhysicalDeviceSampleLocationsPropertiesEXT::sampleLocationCoordinateRange);
        sampleLocationSubPixelBits                                = &(VkPhysicalDeviceSampleLocationsPropertiesEXT::sampleLocationSubPixelBits);
        variableSampleLocations                                   = &(VkPhysicalDeviceSampleLocationsPropertiesEXT::variableSampleLocations);
        shaderBinaryUUID                                          = &(VkPhysicalDeviceShaderObjectPropertiesEXT::shaderBinaryUUID);
        shaderBinaryVersion                                       = &(VkPhysicalDeviceShaderObjectPropertiesEXT::shaderBinaryVersion);
        shaderTileImageCoherentReadAccelerated                    = &(VkPhysicalDeviceShaderTileImagePropertiesEXT::shaderTileImageCoherentReadAccelerated);
        shaderTileImageReadSampleFromPixelRateInvocation          = &(VkPhysicalDeviceShaderTileImagePropertiesEXT::shaderTileImageReadSampleFromPixelRateInvocation);
        shaderTileImageReadFromHelperInvocation                   = &(VkPhysicalDeviceShaderTileImagePropertiesEXT::shaderTileImageReadFromHelperInvocation);
        maxTransformFeedbackStreams                               = &(VkPhysicalDeviceTransformFeedbackPropertiesEXT::maxTransformFeedbackStreams);
        maxTransformFeedbackBuffers                               = &(VkPhysicalDeviceTransformFeedbackPropertiesEXT::maxTransformFeedbackBuffers);
        maxTransformFeedbackBufferSize                            = &(VkPhysicalDeviceTransformFeedbackPropertiesEXT::maxTransformFeedbackBufferSize);
        maxTransformFeedbackStreamDataSize                        = &(VkPhysicalDeviceTransformFeedbackPropertiesEXT::maxTransformFeedbackStreamDataSize);
        maxTransformFeedbackBufferDataSize                        = &(VkPhysicalDeviceTransformFeedbackPropertiesEXT::maxTransformFeedbackBufferDataSize);
        maxTransformFeedbackBufferDataStride                      = &(VkPhysicalDeviceTransformFeedbackPropertiesEXT::maxTransformFeedbackBufferDataStride);
        transformFeedbackQueries                                  = &(VkPhysicalDeviceTransformFeedbackPropertiesEXT::transformFeedbackQueries);
        transformFeedbackStreamsLinesTriangles                    = &(VkPhysicalDeviceTransformFeedbackPropertiesEXT::transformFeedbackStreamsLinesTriangles);
        transformFeedbackRasterizationStreamSelect                = &(VkPhysicalDeviceTransformFeedbackPropertiesEXT::transformFeedbackRasterizationStreamSelect);
        transformFeedbackDraw                                     = &(VkPhysicalDeviceTransformFeedbackPropertiesEXT::transformFeedbackDraw);
        maxVertexAttribDivisor                                    = &(VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT::maxVertexAttribDivisor);

        // Daisy chain
        VkPhysicalDeviceBlendOperationAdvancedPropertiesEXT::pNext      = (static_cast<VkPhysicalDeviceConservativeRasterizationPropertiesEXT*>(this));
        VkPhysicalDeviceConservativeRasterizationPropertiesEXT::pNext   = (static_cast<VkPhysicalDeviceCustomBorderColorPropertiesEXT*>(this));
        VkPhysicalDeviceCustomBorderColorPropertiesEXT::pNext           = (static_cast<VkPhysicalDeviceDescriptorBufferDensityMapPropertiesEXT*>(this));
        VkPhysicalDeviceDescriptorBufferDensityMapPropertiesEXT::pNext  = (static_cast<VkPhysicalDeviceDescriptorBufferPropertiesEXT*>(this));
        VkPhysicalDeviceDescriptorBufferPropertiesEXT::pNext            = (static_cast<VkPhysicalDeviceDeviceGeneratedCommandsPropertiesEXT*>(this));
        VkPhysicalDeviceDeviceGeneratedCommandsPropertiesEXT::pNext     = (static_cast<VkPhysicalDeviceDiscardRectanglePropertiesEXT*>(this));
        VkPhysicalDeviceDiscardRectanglePropertiesEXT::pNext            = (static_cast<VkPhysicalDeviceDrmPropertiesEXT*>(this));
        VkPhysicalDeviceDrmPropertiesEXT::pNext                         = (static_cast<VkPhysicalDeviceExtendedDynamicState3PropertiesEXT*>(this));
        VkPhysicalDeviceExtendedDynamicState3PropertiesEXT::pNext       = (static_cast<VkPhysicalDeviceExternalMemoryHostPropertiesEXT*>(this));
        VkPhysicalDeviceExternalMemoryHostPropertiesEXT::pNext          = (static_cast<VkPhysicalDeviceFragmentDensityMapPropertiesEXT*>(this));
        VkPhysicalDeviceFragmentDensityMapPropertiesEXT::pNext          = (static_cast<VkPhysicalDeviceFragmentDensityMap2PropertiesEXT*>(this));
        VkPhysicalDeviceFragmentDensityMap2PropertiesEXT::pNext         = (static_cast<VkPhysicalDeviceFragmentDensityMapOffsetPropertiesEXT*>(this));
        VkPhysicalDeviceFragmentDensityMapOffsetPropertiesEXT::pNext    = (static_cast<VkPhysicalDeviceGraphicsPipelineLibraryPropertiesEXT*>(this));
        VkPhysicalDeviceGraphicsPipelineLibraryPropertiesEXT::pNext     = (static_cast<VkPhysicalDeviceLegacyVertexAttributesPropertiesEXT*>(this));
        VkPhysicalDeviceLegacyVertexAttributesPropertiesEXT::pNext      = (static_cast<VkPhysicalDeviceMapMemoryPlacedPropertiesEXT*>(this));
        VkPhysicalDeviceMapMemoryPlacedPropertiesEXT::pNext             = (static_cast<VkPhysicalDeviceMemoryBudgetPropertiesEXT*>(this));
        VkPhysicalDeviceMemoryBudgetPropertiesEXT::pNext                = (static_cast<VkPhysicalDeviceMemoryDecompressionPropertiesEXT*>(this));
        VkPhysicalDeviceMemoryDecompressionPropertiesEXT::pNext         = (static_cast<VkPhysicalDeviceMeshShaderPropertiesEXT*>(this));
        VkPhysicalDeviceMeshShaderPropertiesEXT::pNext                  = (static_cast<VkPhysicalDeviceMultiDrawPropertiesEXT*>(this));
        VkPhysicalDeviceMultiDrawPropertiesEXT::pNext                   = (static_cast<VkPhysicalDeviceNestedCommandBufferPropertiesEXT*>(this));
        VkPhysicalDeviceNestedCommandBufferPropertiesEXT::pNext         = (static_cast<VkPhysicalDeviceOpacityMicromapPropertiesEXT*>(this));
        VkPhysicalDeviceOpacityMicromapPropertiesEXT::pNext             = (static_cast<VkPhysicalDevicePCIBusInfoPropertiesEXT*>(this));
        VkPhysicalDevicePCIBusInfoPropertiesEXT::pNext                  = (static_cast<VkPhysicalDevicePipelinePropertiesFeaturesEXT*>(this));
        VkPhysicalDevicePipelinePropertiesFeaturesEXT::pNext            = (static_cast<VkPhysicalDeviceProvokingVertexPropertiesEXT*>(this));
        VkPhysicalDeviceProvokingVertexPropertiesEXT::pNext             = (static_cast<VkPhysicalDeviceRayTracingInvocationReorderPropertiesEXT*>(this));
        VkPhysicalDeviceRayTracingInvocationReorderPropertiesEXT::pNext = (static_cast<VkPhysicalDeviceSampleLocationsPropertiesEXT*>(this));
        VkPhysicalDeviceSampleLocationsPropertiesEXT::pNext             = (static_cast<VkPhysicalDeviceShaderObjectPropertiesEXT*>(this));
        VkPhysicalDeviceShaderObjectPropertiesEXT::pNext                = (static_cast<VkPhysicalDeviceShaderTileImagePropertiesEXT*>(this));
        VkPhysicalDeviceShaderTileImagePropertiesEXT::pNext             = (static_cast<VkPhysicalDeviceTransformFeedbackPropertiesEXT*>(this));
        VkPhysicalDeviceTransformFeedbackPropertiesEXT::pNext           = (static_cast<VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT*>(this));
        VkPhysicalDeviceVertexAttributeDivisorPropertiesEXT::pNext      = nullptr;

    }
};


///
/// \brief Struct representing the properties of a physical device.
struct device_properties : private VkPhysicalDeviceProperties2,
                           private VkPhysicalDeviceMemoryProperties2,
                           private device_properties_11,
                           private device_properties_12,
                           private device_properties_13,
                           private device_properties_14,
                           private device_properties_khr,
                           private device_properties_ext {

// Constructors & Destructor -------------------------------------------------------------------------------------------
public:

    VkPhysicalDeviceProperties* core10;
    VkPhysicalDeviceMemoryProperties* memory;


    /// \name Constructors & Destructor
    /// @{

    ///
    /// \brief Device Constructor
    /// \param device The device to acquire properties from
    explicit device_properties(VkPhysicalDevice device)
        : VkPhysicalDeviceProperties2 {
            [&]() -> VkPhysicalDeviceProperties2 { // Disgusting trick to handle initialization order
                vkGetPhysicalDeviceProperties(device, &(VkPhysicalDeviceProperties2::properties));
                return *static_cast<VkPhysicalDeviceProperties2*>(this);
            }()
        }
        , device_properties_11(VkPhysicalDeviceProperties2::properties)
        , device_properties_12(VkPhysicalDeviceProperties2::properties)
        , device_properties_13(VkPhysicalDeviceProperties2::properties)
        , device_properties_14(VkPhysicalDeviceProperties2::properties)
        , core10(&(VkPhysicalDeviceProperties2::properties))
        , memory(&(VkPhysicalDeviceMemoryProperties2::memoryProperties)) {

        // Acquire all properties after Core 1.0 if available
        if (vkGetPhysicalDeviceProperties2) {
            vkGetPhysicalDeviceProperties2(device, this);
        }


        //
        if (vkGetPhysicalDeviceMemoryProperties2) {
            vkGetPhysicalDeviceMemoryProperties2(device, this);
        } else {
            vkGetPhysicalDeviceMemoryProperties(device, &(VkPhysicalDeviceMemoryProperties2::memoryProperties));
        }
    }

    device_properties(const device_properties& props)
        : VkPhysicalDeviceProperties2 { props }
        , device_properties_11(props)
        , device_properties_12(props)
        , device_properties_13(props)
        , device_properties_14(props)
        , device_properties_khr(props)
        , device_properties_ext(props)
        , core10(&(VkPhysicalDeviceProperties2::properties)) {
    }

    device_properties& operator=(const device_properties& props) {
        if (&props == this) {
            return *this;
        }

        VkPhysicalDeviceProperties2::operator=(props);
        VkPhysicalDeviceProperties2::operator=(props);
        VkPhysicalDeviceProperties2::operator=(props);
        VkPhysicalDeviceProperties2::operator=(props);
        VkPhysicalDeviceProperties2::operator=(props);
        VkPhysicalDeviceProperties2::operator=(props);
        VkPhysicalDeviceProperties2::operator=(props);

        return *this;
    }

    /// @}
};

}

#endif // FENNEC_RENDERERS_VULKAN_LIB_PHYSICAL_DEVICE_PROPERTIES_H