/* * Copyright (c) 2015-2016 The Khronos Group Inc. * Copyright (c) 2015-2016 Valve Corporation * Copyright (c) 2015-2016 LunarG, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and/or associated documentation files (the "Materials"), to * deal in the Materials without restriction, including without limitation the * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or * sell copies of the Materials, and to permit persons to whom the Materials are * furnished to do so, subject to the following conditions: * * The above copyright notice(s) and this permission notice shall be included in * all copies or substantial portions of the Materials. * * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE * USE OR OTHER DEALINGS IN THE MATERIALS. * * Author: Jeremy Hayes */ #include #include #include #include #include #include "test_common.h" #include namespace VK { struct InstanceCreateInfo { InstanceCreateInfo() : info // MSVC can't handle list initialization, thus explicit construction herein. (VkInstanceCreateInfo{ VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // sType nullptr, // pNext 0, // flags nullptr, // pApplicationInfo 0, // enabledLayerCount nullptr, // ppEnabledLayerNames 0, // enabledExtensionCount nullptr // ppEnabledExtensionNames }) {} InstanceCreateInfo &sType(VkStructureType const &sType) { info.sType = sType; return *this; } InstanceCreateInfo &pNext(void const *const pNext) { info.pNext = pNext; return *this; } InstanceCreateInfo &flags(VkInstanceCreateFlags const &flags) { info.flags = flags; return *this; } InstanceCreateInfo &pApplicationInfo(VkApplicationInfo const *const pApplicationInfo) { info.pApplicationInfo = pApplicationInfo; return *this; } InstanceCreateInfo &enabledLayerCount(uint32_t const &enabledLayerCount) { info.enabledLayerCount = enabledLayerCount; return *this; } InstanceCreateInfo &ppEnabledLayerNames(char const *const *const ppEnabledLayerNames) { info.ppEnabledLayerNames = ppEnabledLayerNames; return *this; } InstanceCreateInfo &enabledExtensionCount(uint32_t const &enabledExtensionCount) { info.enabledExtensionCount = enabledExtensionCount; return *this; } InstanceCreateInfo &ppEnabledExtensionNames(char const *const *const ppEnabledExtensionNames) { info.ppEnabledExtensionNames = ppEnabledExtensionNames; return *this; } operator VkInstanceCreateInfo const *() const { return &info; } operator VkInstanceCreateInfo *() { return &info; } VkInstanceCreateInfo info; }; struct DeviceQueueCreateInfo { DeviceQueueCreateInfo() : info // MSVC can't handle list initialization, thus explicit construction herein. (VkDeviceQueueCreateInfo{ VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType nullptr, // pNext 0, // flags 0, // queueFamilyIndex 0, // queueCount nullptr // pQueuePriorities }) {} DeviceQueueCreateInfo &sType(VkStructureType const &sType) { info.sType = sType; return *this; } DeviceQueueCreateInfo &pNext(void const *const pNext) { info.pNext = pNext; return *this; } DeviceQueueCreateInfo &flags(VkDeviceQueueCreateFlags const &flags) { info.flags = flags; return *this; } DeviceQueueCreateInfo &queueFamilyIndex(uint32_t const &queueFamilyIndex) { info.queueFamilyIndex = queueFamilyIndex; return *this; } DeviceQueueCreateInfo &queueCount(uint32_t const &queueCount) { info.queueCount = queueCount; return *this; } DeviceQueueCreateInfo &pQueuePriorities(float const *const pQueuePriorities) { info.pQueuePriorities = pQueuePriorities; return *this; } operator VkDeviceQueueCreateInfo() { return info; } VkDeviceQueueCreateInfo info; }; struct DeviceCreateInfo { DeviceCreateInfo() : info // MSVC can't handle list initialization, thus explicit construction herein. (VkDeviceCreateInfo{ VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType nullptr, // pNext 0, // flags 0, // queueCreateInfoCount nullptr, // pQueueCreateInfos 0, // enabledLayerCount nullptr, // ppEnabledLayerNames 0, // enabledExtensionCount nullptr, // ppEnabledExtensionNames nullptr // pEnabledFeatures }) {} DeviceCreateInfo &sType(VkStructureType const &sType) { info.sType = sType; return *this; } DeviceCreateInfo &pNext(void const *const pNext) { info.pNext = pNext; return *this; } DeviceCreateInfo &flags(VkDeviceQueueCreateFlags const &flags) { info.flags = flags; return *this; } DeviceCreateInfo &queueCreateInfoCount(uint32_t const &queueCreateInfoCount) { info.queueCreateInfoCount = queueCreateInfoCount; return *this; } DeviceCreateInfo &pQueueCreateInfos(VkDeviceQueueCreateInfo const *const pQueueCreateInfos) { info.pQueueCreateInfos = pQueueCreateInfos; return *this; } DeviceCreateInfo &enabledLayerCount(uint32_t const &enabledLayerCount) { info.enabledLayerCount = enabledLayerCount; return *this; } DeviceCreateInfo &ppEnabledLayerNames(char const *const *const ppEnabledLayerNames) { info.ppEnabledLayerNames = ppEnabledLayerNames; return *this; } DeviceCreateInfo &enabledExtensionCount(uint32_t const &enabledExtensionCount) { info.enabledExtensionCount = enabledExtensionCount; return *this; } DeviceCreateInfo &ppEnabledExtensionNames(char const *const *const ppEnabledExtensionNames) { info.ppEnabledExtensionNames = ppEnabledExtensionNames; return *this; } DeviceCreateInfo &pEnabledFeatures(VkPhysicalDeviceFeatures const *const pEnabledFeatures) { info.pEnabledFeatures = pEnabledFeatures; return *this; } operator VkDeviceCreateInfo const *() const { return &info; } operator VkDeviceCreateInfo *() { return &info; } VkDeviceCreateInfo info; }; } struct CommandLine : public ::testing::Test { static void Initialize(int argc, char **argv) { arguments.assign(argv, argv + argc); }; static void SetUpTestCase(){}; static void TearDownTestCase(){}; static std::vector arguments; }; std::vector CommandLine::arguments; struct EnumerateInstanceLayerProperties : public CommandLine {}; struct EnumerateInstanceExtensionProperties : public CommandLine {}; struct ImplicitLayer : public CommandLine {}; // Test groups: // LX = lunar exchange // LVLGH = loader and validation github // LVLGL = lodaer and validation gitlab TEST(LX435, InstanceCreateInfoConst) { VkInstanceCreateInfo const info = {VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, nullptr, 0, nullptr, 0, nullptr, 0, nullptr}; VkInstance instance = VK_NULL_HANDLE; VkResult result = vkCreateInstance(&info, VK_NULL_HANDLE, &instance); EXPECT_EQ(result, VK_SUCCESS); vkDestroyInstance(instance, nullptr); } TEST(LX475, DestroyInstanceNullHandle) { vkDestroyInstance(VK_NULL_HANDLE, nullptr); } TEST(LX475, DestroyDeviceNullHandle) { vkDestroyDevice(VK_NULL_HANDLE, nullptr); } TEST(CreateInstance, ExtensionNotPresent) { char const *const names[] = {"NotPresent"}; // Temporary required due to MSVC bug. auto const info = VK::InstanceCreateInfo().enabledExtensionCount(1).ppEnabledExtensionNames(names); VkInstance instance = VK_NULL_HANDLE; VkResult result = vkCreateInstance(info, VK_NULL_HANDLE, &instance); ASSERT_EQ(result, VK_ERROR_EXTENSION_NOT_PRESENT); // It's not necessary to destroy the instance because it will not be created successfully. } TEST(CreateInstance, LayerNotPresent) { char const *const names[] = {"NotPresent"}; // Temporary required due to MSVC bug. auto const info = VK::InstanceCreateInfo().enabledLayerCount(1).ppEnabledLayerNames(names); VkInstance instance = VK_NULL_HANDLE; VkResult result = vkCreateInstance(info, VK_NULL_HANDLE, &instance); ASSERT_EQ(result, VK_ERROR_LAYER_NOT_PRESENT); // It's not necessary to destroy the instance because it will not be created successfully. } // Used by run_loader_tests.sh to test for layer insertion. TEST(CreateInstance, LayerPresent) { char const *const names[] = {"VK_LAYER_LUNARG_parameter_validation"}; // Temporary required due to MSVC bug. auto const info = VK::InstanceCreateInfo().enabledLayerCount(1).ppEnabledLayerNames(names); VkInstance instance = VK_NULL_HANDLE; VkResult result = vkCreateInstance(info, VK_NULL_HANDLE, &instance); ASSERT_EQ(result, VK_SUCCESS); vkDestroyInstance(instance, nullptr); } TEST(CreateDevice, ExtensionNotPresent) { VkInstance instance = VK_NULL_HANDLE; VkResult result = vkCreateInstance(VK::InstanceCreateInfo(), VK_NULL_HANDLE, &instance); ASSERT_EQ(result, VK_SUCCESS); uint32_t physicalCount = 0; result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr); ASSERT_EQ(result, VK_SUCCESS); ASSERT_GT(physicalCount, 0u); std::unique_ptr physical(new VkPhysicalDevice[physicalCount]); result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get()); ASSERT_EQ(result, VK_SUCCESS); ASSERT_GT(physicalCount, 0u); for (uint32_t p = 0; p < physicalCount; ++p) { uint32_t familyCount = 0; vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, nullptr); ASSERT_EQ(result, VK_SUCCESS); ASSERT_GT(familyCount, 0u); std::unique_ptr family(new VkQueueFamilyProperties[familyCount]); vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, family.get()); ASSERT_EQ(result, VK_SUCCESS); ASSERT_GT(familyCount, 0u); for (uint32_t q = 0; q < familyCount; ++q) { if (~family[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) { continue; } float const priorities[] = {0.0f}; // Temporary required due to MSVC bug. VkDeviceQueueCreateInfo const queueInfo[1]{ VK::DeviceQueueCreateInfo().queueFamilyIndex(q).queueCount(1).pQueuePriorities(priorities)}; char const *const names[] = {"NotPresent"}; // Temporary required due to MSVC bug. auto const deviceInfo = VK::DeviceCreateInfo() .queueCreateInfoCount(1) .pQueueCreateInfos(queueInfo) .enabledExtensionCount(1) .ppEnabledExtensionNames(names); VkDevice device; result = vkCreateDevice(physical[p], deviceInfo, nullptr, &device); ASSERT_EQ(result, VK_ERROR_EXTENSION_NOT_PRESENT); // It's not necessary to destroy the device because it will not be created successfully. } } vkDestroyInstance(instance, nullptr); } // LX535 / MI-76: Device layers are deprecated. // For backwards compatibility, they are allowed, but must be ignored. // Ensure that no errors occur if a bogus device layer list is passed to vkCreateDevice. TEST(CreateDevice, LayersNotPresent) { VkInstance instance = VK_NULL_HANDLE; VkResult result = vkCreateInstance(VK::InstanceCreateInfo(), VK_NULL_HANDLE, &instance); ASSERT_EQ(result, VK_SUCCESS); uint32_t physicalCount = 0; result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr); ASSERT_EQ(result, VK_SUCCESS); ASSERT_GT(physicalCount, 0u); std::unique_ptr physical(new VkPhysicalDevice[physicalCount]); result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get()); ASSERT_EQ(result, VK_SUCCESS); ASSERT_GT(physicalCount, 0u); for (uint32_t p = 0; p < physicalCount; ++p) { uint32_t familyCount = 0; vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, nullptr); ASSERT_EQ(result, VK_SUCCESS); ASSERT_GT(familyCount, 0u); std::unique_ptr family(new VkQueueFamilyProperties[familyCount]); vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, family.get()); ASSERT_EQ(result, VK_SUCCESS); ASSERT_GT(familyCount, 0u); for (uint32_t q = 0; q < familyCount; ++q) { if (~family[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) { continue; } float const priorities[] = {0.0f}; // Temporary required due to MSVC bug. VkDeviceQueueCreateInfo const queueInfo[1]{ VK::DeviceQueueCreateInfo().queueFamilyIndex(q).queueCount(1).pQueuePriorities(priorities)}; char const *const names[] = {"NotPresent"}; // Temporary required due to MSVC bug. auto const deviceInfo = VK::DeviceCreateInfo() .queueCreateInfoCount(1) .pQueueCreateInfos(queueInfo) .enabledLayerCount(1) .ppEnabledLayerNames(names); VkDevice device; result = vkCreateDevice(physical[p], deviceInfo, nullptr, &device); ASSERT_EQ(result, VK_SUCCESS); vkDestroyDevice(device, nullptr); } } vkDestroyInstance(instance, nullptr); } TEST_F(EnumerateInstanceLayerProperties, PropertyCountLessThanAvailable) { uint32_t count = 0u; VkResult result = vkEnumerateInstanceLayerProperties(&count, nullptr); ASSERT_EQ(result, VK_SUCCESS); // We need atleast two for the test to be relevant. if (count < 2u) { return; } std::unique_ptr properties(new VkLayerProperties[count]); count = 1; result = vkEnumerateInstanceLayerProperties(&count, properties.get()); ASSERT_EQ(result, VK_INCOMPLETE); } TEST(EnumerateDeviceLayerProperties, PropertyCountLessThanAvailable) { VkInstance instance = VK_NULL_HANDLE; VkResult result = vkCreateInstance(VK::InstanceCreateInfo(), VK_NULL_HANDLE, &instance); ASSERT_EQ(result, VK_SUCCESS); uint32_t physicalCount = 0; result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr); ASSERT_EQ(result, VK_SUCCESS); ASSERT_GT(physicalCount, 0u); std::unique_ptr physical(new VkPhysicalDevice[physicalCount]); result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get()); ASSERT_EQ(result, VK_SUCCESS); ASSERT_GT(physicalCount, 0u); for (uint32_t p = 0; p < physicalCount; ++p) { uint32_t count = 0u; result = vkEnumerateDeviceLayerProperties(physical[p], &count, nullptr); ASSERT_EQ(result, VK_SUCCESS); // We need atleast two for the test to be relevant. if (count < 2u) { continue; } std::unique_ptr properties(new VkLayerProperties[count]); count = 1; result = vkEnumerateDeviceLayerProperties(physical[p], &count, properties.get()); ASSERT_EQ(result, VK_INCOMPLETE); } vkDestroyInstance(instance, nullptr); } TEST_F(EnumerateInstanceLayerProperties, Count) { uint32_t count = 0u; VkResult result = vkEnumerateInstanceLayerProperties(&count, nullptr); ASSERT_EQ(result, VK_SUCCESS); if (std::find(arguments.begin(), arguments.end(), "count") != arguments.end()) { std::cout << "count=" << count << '\n'; } } TEST_F(EnumerateInstanceLayerProperties, OnePass) { // Count required for this test. if (std::find(arguments.begin(), arguments.end(), "count") == arguments.end()) { return; } uint32_t count = std::stoul(arguments[2]); std::unique_ptr properties(new VkLayerProperties[count]); VkResult result = vkEnumerateInstanceLayerProperties(&count, properties.get()); ASSERT_EQ(result, VK_SUCCESS); if (std::find(arguments.begin(), arguments.end(), "properties") != arguments.end()) { for (uint32_t p = 0; p < count; ++p) { std::cout << "properties[" << p << "] =" << ' ' << properties[p].layerName << ' ' << properties[p].specVersion << ' ' << properties[p].implementationVersion << ' ' << properties[p].description << '\n'; } } } TEST_F(EnumerateInstanceLayerProperties, TwoPass) { uint32_t count = 0u; VkResult result = vkEnumerateInstanceLayerProperties(&count, nullptr); ASSERT_EQ(result, VK_SUCCESS); std::unique_ptr properties(new VkLayerProperties[count]); result = vkEnumerateInstanceLayerProperties(&count, properties.get()); ASSERT_EQ(result, VK_SUCCESS); if (std::find(arguments.begin(), arguments.end(), "properties") != arguments.end()) { for (uint32_t p = 0; p < count; ++p) { std::cout << "properties[" << p << "] =" << ' ' << properties[p].layerName << ' ' << properties[p].specVersion << ' ' << properties[p].implementationVersion << ' ' << properties[p].description << '\n'; } } } TEST_F(EnumerateInstanceExtensionProperties, PropertyCountLessThanAvailable) { uint32_t count = 0u; VkResult result = vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr); ASSERT_EQ(result, VK_SUCCESS); // We need atleast two for the test to be relevant. if (count < 2u) { return; } std::unique_ptr properties(new VkExtensionProperties[count]); count = 1; result = vkEnumerateInstanceExtensionProperties(nullptr, &count, properties.get()); ASSERT_EQ(result, VK_INCOMPLETE); } TEST(EnumerateDeviceExtensionProperties, PropertyCountLessThanAvailable) { VkInstance instance = VK_NULL_HANDLE; VkResult result = vkCreateInstance(VK::InstanceCreateInfo(), VK_NULL_HANDLE, &instance); ASSERT_EQ(result, VK_SUCCESS); uint32_t physicalCount = 0; result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr); ASSERT_EQ(result, VK_SUCCESS); ASSERT_GT(physicalCount, 0u); std::unique_ptr physical(new VkPhysicalDevice[physicalCount]); result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get()); ASSERT_EQ(result, VK_SUCCESS); ASSERT_GT(physicalCount, 0u); for (uint32_t p = 0; p < physicalCount; ++p) { uint32_t count = 0u; result = vkEnumerateDeviceExtensionProperties(physical[p], nullptr, &count, nullptr); ASSERT_EQ(result, VK_SUCCESS); // We need atleast two for the test to be relevant. if (count < 2u) { continue; } std::unique_ptr properties(new VkExtensionProperties[count]); count = 1; result = vkEnumerateDeviceExtensionProperties(physical[p], nullptr, &count, properties.get()); ASSERT_EQ(result, VK_INCOMPLETE); } vkDestroyInstance(instance, nullptr); } TEST_F(EnumerateInstanceExtensionProperties, Count) { uint32_t count = 0u; VkResult result = vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr); ASSERT_EQ(result, VK_SUCCESS); if (std::find(arguments.begin(), arguments.end(), "count") != arguments.end()) { std::cout << "count=" << count << '\n'; } } TEST_F(EnumerateInstanceExtensionProperties, OnePass) { // Count required for this test. if (std::find(arguments.begin(), arguments.end(), "count") == arguments.end()) { return; } uint32_t count = std::stoul(arguments[2]); std::unique_ptr properties(new VkExtensionProperties[count]); VkResult result = vkEnumerateInstanceExtensionProperties(nullptr, &count, properties.get()); ASSERT_EQ(result, VK_SUCCESS); if (std::find(arguments.begin(), arguments.end(), "properties") != arguments.end()) { for (uint32_t p = 0; p < count; ++p) { std::cout << "properties[" << p << "] =" << ' ' << properties[p].extensionName << ' ' << properties[p].specVersion << '\n'; } } } TEST_F(EnumerateInstanceExtensionProperties, TwoPass) { uint32_t count = 0u; VkResult result = vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr); ASSERT_EQ(result, VK_SUCCESS); std::unique_ptr properties(new VkExtensionProperties[count]); result = vkEnumerateInstanceExtensionProperties(nullptr, &count, properties.get()); ASSERT_EQ(result, VK_SUCCESS); if (std::find(arguments.begin(), arguments.end(), "properties") != arguments.end()) { for (uint32_t p = 0; p < count; ++p) { std::cout << "properties[" << p << "] =" << ' ' << properties[p].extensionName << ' ' << properties[p].specVersion << '\n'; } } } TEST_F(EnumerateInstanceExtensionProperties, InstanceExtensionEnumerated) { uint32_t count = 0u; VkResult result = vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr); ASSERT_EQ(result, VK_SUCCESS); std::unique_ptr properties(new VkExtensionProperties[count]); result = vkEnumerateInstanceExtensionProperties(nullptr, &count, properties.get()); ASSERT_EQ(result, VK_SUCCESS); ASSERT_NE(std::find_if( &properties[0], &properties[count], [](VkExtensionProperties const &properties) { return strcmp(properties.extensionName, "VK_KHR_surface") == 0; }), &properties[count]); } TEST(EnumerateDeviceExtensionProperties, DeviceExtensionEnumerated) { VkInstance instance = VK_NULL_HANDLE; VkResult result = vkCreateInstance(VK::InstanceCreateInfo(), VK_NULL_HANDLE, &instance); ASSERT_EQ(result, VK_SUCCESS); uint32_t physicalCount = 0; result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr); ASSERT_EQ(result, VK_SUCCESS); ASSERT_GT(physicalCount, 0u); std::unique_ptr physical(new VkPhysicalDevice[physicalCount]); result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get()); ASSERT_EQ(result, VK_SUCCESS); ASSERT_GT(physicalCount, 0u); for (uint32_t p = 0; p < physicalCount; ++p) { uint32_t count = 0u; result = vkEnumerateDeviceExtensionProperties(physical[p], nullptr, &count, nullptr); ASSERT_EQ(result, VK_SUCCESS); std::unique_ptr properties(new VkExtensionProperties[count]); result = vkEnumerateDeviceExtensionProperties(physical[p], nullptr, &count, properties.get()); ASSERT_EQ(result, VK_SUCCESS); ASSERT_NE(std::find_if(&properties[0], &properties[count], [](VkExtensionProperties const &properties) { return strcmp(properties.extensionName, "VK_KHR_swapchain") == 0; }), &properties[count]); } vkDestroyInstance(instance, nullptr); } TEST_F(ImplicitLayer, Present) { auto const info = VK::InstanceCreateInfo(); VkInstance instance = VK_NULL_HANDLE; VkResult result = vkCreateInstance(info, VK_NULL_HANDLE, &instance); ASSERT_EQ(result, VK_SUCCESS); vkDestroyInstance(instance, nullptr); } TEST(WrapObjects, Insert) { VkInstance instance = VK_NULL_HANDLE; VkResult result = vkCreateInstance(VK::InstanceCreateInfo(), VK_NULL_HANDLE, &instance); ASSERT_EQ(result, VK_SUCCESS); uint32_t physicalCount = 0; result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr); ASSERT_EQ(result, VK_SUCCESS); ASSERT_GT(physicalCount, 0u); std::unique_ptr physical(new VkPhysicalDevice[physicalCount]); result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get()); ASSERT_EQ(result, VK_SUCCESS); ASSERT_GT(physicalCount, 0u); for (uint32_t p = 0; p < physicalCount; ++p) { uint32_t familyCount = 0; vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, nullptr); ASSERT_EQ(result, VK_SUCCESS); ASSERT_GT(familyCount, 0u); std::unique_ptr family(new VkQueueFamilyProperties[familyCount]); vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, family.get()); ASSERT_EQ(result, VK_SUCCESS); ASSERT_GT(familyCount, 0u); for (uint32_t q = 0; q < familyCount; ++q) { if (~family[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) { continue; } float const priorities[] = {0.0f}; // Temporary required due to MSVC bug. VkDeviceQueueCreateInfo const queueInfo[1]{ VK::DeviceQueueCreateInfo().queueFamilyIndex(q).queueCount(1).pQueuePriorities(priorities)}; auto const deviceInfo = VK::DeviceCreateInfo().queueCreateInfoCount(1).pQueueCreateInfos(queueInfo); VkDevice device; result = vkCreateDevice(physical[p], deviceInfo, nullptr, &device); ASSERT_EQ(result, VK_SUCCESS); vkDestroyDevice(device, nullptr); } } vkDestroyInstance(instance, nullptr); } int main(int argc, char **argv) { int result; ::testing::InitGoogleTest(&argc, argv); if (argc > 0) { CommandLine::Initialize(argc, argv); } result = RUN_ALL_TESTS(); return result; }