0
votes

When using the function vkGetPhysicalDeviceProperties2 I pass a VkPhysicalDeviceProperties2 struct with a VkPhysicalDeviceVulkan11Properties and VkPhysicalDeviceVulkan12Properties in the pNext chain. However, after calling the function, only the vkGetPhysicalDeviceProperties2 contains valid data, the other structures in the chain contain undefined data.

When reviewing the spec, I noticed the comment about other structures Vulkan11 and Vulkan12 structures are supposed to encompass. When replacing them with their corresponding "smaller" structures and adding them to the chain. I do get valid data, which seems even stranger since I don't see what's preventing Vulkan from using the larger structures in the first place.

Note: Validation layers are silent

Info:

  • Vulkan SDK: 1.2.141.0
  • Nvidia Driver: 446.14
  • GPU GeForce GTX 1060 with Max-Q Design
  • OS: Windows 10.0.18363
  • Compiler: Microsoft (R) C/C++ Optimizing Compiler Version 19.26.28806 for x64

Relevant Code:

StaticArray<char const *, 1> const RequiredInstanceLayers{
    "VK_LAYER_KHRONOS_validation",
};
StaticArray<char const *, 3> const RequiredInstanceExtensions{
    VK_KHR_SURFACE_EXTENSION_NAME,
    VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
    VK_KHR_WIN32_SURFACE_EXTENSION_NAME,
};
VkApplicationInfo ApplicationInfo;
ApplicationInfo.sType              = VK_STRUCTURE_TYPE_APPLICATION_INFO;
ApplicationInfo.pNext              = nullptr;
ApplicationInfo.pApplicationName   = "Application";
ApplicationInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
ApplicationInfo.pEngineName        = "Engine";
ApplicationInfo.engineVersion      = VK_MAKE_VERSION(1, 0, 0);
ApplicationInfo.apiVersion         = VK_API_VERSION_1_2;
VkInstanceCreateInfo InstanceCreateInfo;
InstanceCreateInfo.sType                   = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
InstanceCreateInfo.pNext                   = nullptr;
InstanceCreateInfo.flags                   = 0;
InstanceCreateInfo.pApplicationInfo        = &ApplicationInfo;
InstanceCreateInfo.enabledLayerCount       = RequiredInstanceLayers.length;
InstanceCreateInfo.ppEnabledLayerNames     = RequiredInstanceLayers.data;
InstanceCreateInfo.enabledExtensionCount   = RequiredInstanceExtensions.length;
InstanceCreateInfo.ppEnabledExtensionNames = RequiredInstanceExtensions.data;
vkCreateInstance(&InstanceCreateInfo, nullptr, &m_instance);

Uint32 physical_device_count;
vkEnumeratePhysicalDevices(m_instance, &physical_device_count, nullptr);
m_available_physical_devices.Create(m_allocator, physical_device_count);
vkEnumeratePhysicalDevices(m_instance, &physical_device_count, m_available_physical_devices.beg);

for (auto it = m_available_physical_devices.beg; it != m_available_physical_devices.end; ++it)
{
    { // Test 1
        VkPhysicalDeviceProperties2 Properties2;
        VkPhysicalDeviceVulkan11Properties Vulkan11Properties;
        VkPhysicalDeviceVulkan12Properties Vulkan12Properties;
        Properties2.sType        = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
        Vulkan11Properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES;
        Vulkan12Properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_PROPERTIES;
        Properties2.pNext        = &Vulkan11Properties;
        Vulkan11Properties.pNext = &Vulkan12Properties;
        Vulkan12Properties.pNext = nullptr;
        vkGetPhysicalDeviceProperties2(*it, &Properties2); // only Properties2 is filled out
        // Vulkan11Properties and Vulkan12Properties contain undefined data
    }
    { // Test 2
        VkPhysicalDeviceProperties2                   Properties2;
        VkPhysicalDeviceDriverProperties              DriverProperties;
        VkPhysicalDeviceFloatControlsProperties       FloatControlsProperties;
        VkPhysicalDeviceDescriptorIndexingProperties  DescriptorIndexingProperties;
        VkPhysicalDeviceDepthStencilResolveProperties DepthStencilResolveProperties;
        VkPhysicalDeviceSamplerFilterMinmaxProperties SamplerFilterMinmaxProperties;
        VkPhysicalDeviceTimelineSemaphoreProperties   TimelineSemaphoreProperties;
        VkPhysicalDeviceIDProperties                  IDProperties;
        VkPhysicalDeviceSubgroupProperties            SubgroupProperties;
        VkPhysicalDevicePointClippingProperties       PointClippingProperties;
        VkPhysicalDeviceMultiviewProperties           MultiviewProperties;
        VkPhysicalDeviceProtectedMemoryProperties     ProtectedMemoryProperties;
        VkPhysicalDeviceMaintenance3Properties        Maintenance3Properties;
        Properties2.sType                   = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
        DriverProperties.sType              = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
        FloatControlsProperties.sType       = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FLOAT_CONTROLS_PROPERTIES;
        DescriptorIndexingProperties.sType  = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_PROPERTIES;
        DepthStencilResolveProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES;
        SamplerFilterMinmaxProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_FILTER_MINMAX_PROPERTIES;
        TimelineSemaphoreProperties.sType   = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TIMELINE_SEMAPHORE_PROPERTIES;
        IDProperties.sType                  = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES;
        SubgroupProperties.sType            = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SUBGROUP_PROPERTIES;
        PointClippingProperties.sType       = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_POINT_CLIPPING_PROPERTIES;
        MultiviewProperties.sType           = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_PROPERTIES;
        ProtectedMemoryProperties.sType     = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES;
        Maintenance3Properties.sType        = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_3_PROPERTIES;
        Properties2.pNext                   = &DriverProperties;
        DriverProperties.pNext              = &FloatControlsProperties;
        FloatControlsProperties.pNext       = &DescriptorIndexingProperties;
        DescriptorIndexingProperties.pNext  = &DepthStencilResolveProperties;
        DepthStencilResolveProperties.pNext = &SamplerFilterMinmaxProperties;
        SamplerFilterMinmaxProperties.pNext = &TimelineSemaphoreProperties;
        TimelineSemaphoreProperties.pNext   = &IDProperties;
        IDProperties.pNext                  = &SubgroupProperties;
        SubgroupProperties.pNext            = &PointClippingProperties;
        PointClippingProperties.pNext       = &MultiviewProperties;
        MultiviewProperties.pNext           = &ProtectedMemoryProperties;
        ProtectedMemoryProperties.pNext     = &Maintenance3Properties;
        Maintenance3Properties.pNext        = nullptr;
        vkGetPhysicalDeviceProperties2(*it, &Properties2); // every structure is filled out
    }
}
1

1 Answers

1
votes

Nvidia 446.14 drivers are Vulkan 1.1. VkPhysicalDeviceVulkan11Properties and VkPhysicalDeviceVulkan12Properties both require Vulkan 1.2.

The struct are untouched, because the spec says:

Any component of the implementation (the loader, any enabled layers, and drivers) must skip over, without processing (other than reading the sType and pNext members) any extending structures in the chain not defined by core versions or extensions supported by that component.

On the other hand it is not valid usage:

Each structure present in the pNext chain must be defined at runtime either by a core version which is supported, or by an extension which is enabled.

So Validation layers should ideally be catching this. You should report this at KhronosGroup/Vulkan-ValidationLayers. The problem seems to be the layers check indiscriminately of what version it is, and what extensions are enabled.