| /* | 
 |  * 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 <jeremy@lunarG.com> | 
 |  */ | 
 |  | 
 | #include <memory> | 
 |  | 
 | #include <vulkan/vulkan.h> | 
 | #include "test_common.h" | 
 |  | 
 | 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; | 
 | }; | 
 |  | 
 | } | 
 |  | 
 | // 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); | 
 | } | 
 |  | 
 | 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); | 
 | } | 
 |  | 
 | 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); | 
 | } | 
 |  | 
 | // 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); | 
 | } | 
 |  | 
 | 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<VkPhysicalDevice[]> 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<VkQueueFamilyProperties[]> 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); | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | // 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<VkPhysicalDevice[]> 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<VkQueueFamilyProperties[]> 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); | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | 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<VkPhysicalDevice[]> 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<VkQueueFamilyProperties[]> 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); | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | int main(int argc, char **argv) | 
 | { | 
 |     int result; | 
 |  | 
 |     ::testing::InitGoogleTest(&argc, argv); | 
 |  | 
 |     result = RUN_ALL_TESTS(); | 
 |  | 
 |     return result; | 
 | } |