1/*
2 * Copyright (c) 2015-2016 The Khronos Group Inc.
3 * Copyright (c) 2015-2016 Valve Corporation
4 * Copyright (c) 2015-2016 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and/or associated documentation files (the "Materials"), to
8 * deal in the Materials without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Materials, and to permit persons to whom the Materials are
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice(s) and this permission notice shall be included in
14 * all copies or substantial portions of the Materials.
15 *
16 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 *
20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
23 * USE OR OTHER DEALINGS IN THE MATERIALS.
24 *
25 * Author: Jeremy Hayes <jeremy@lunarG.com>
26 */
27
28#include <algorithm>
29#include <iostream>
30#include <memory>
31#include <string>
32#include <vector>
33
34#include "test_common.h"
35#include <vulkan/vulkan.h>
36
37namespace VK {
38
39struct InstanceCreateInfo {
40    InstanceCreateInfo()
41        : info // MSVC can't handle list initialization, thus explicit construction herein.
42          (VkInstanceCreateInfo{
43              VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // sType
44              nullptr,                                // pNext
45              0,                                      // flags
46              nullptr,                                // pApplicationInfo
47              0,                                      // enabledLayerCount
48              nullptr,                                // ppEnabledLayerNames
49              0,                                      // enabledExtensionCount
50              nullptr                                 // ppEnabledExtensionNames
51          }) {}
52
53    InstanceCreateInfo &sType(VkStructureType const &sType) {
54        info.sType = sType;
55
56        return *this;
57    }
58
59    InstanceCreateInfo &pNext(void const *const pNext) {
60        info.pNext = pNext;
61
62        return *this;
63    }
64
65    InstanceCreateInfo &flags(VkInstanceCreateFlags const &flags) {
66        info.flags = flags;
67
68        return *this;
69    }
70
71    InstanceCreateInfo &pApplicationInfo(VkApplicationInfo const *const pApplicationInfo) {
72        info.pApplicationInfo = pApplicationInfo;
73
74        return *this;
75    }
76
77    InstanceCreateInfo &enabledLayerCount(uint32_t const &enabledLayerCount) {
78        info.enabledLayerCount = enabledLayerCount;
79
80        return *this;
81    }
82
83    InstanceCreateInfo &ppEnabledLayerNames(char const *const *const ppEnabledLayerNames) {
84        info.ppEnabledLayerNames = ppEnabledLayerNames;
85
86        return *this;
87    }
88
89    InstanceCreateInfo &enabledExtensionCount(uint32_t const &enabledExtensionCount) {
90        info.enabledExtensionCount = enabledExtensionCount;
91
92        return *this;
93    }
94
95    InstanceCreateInfo &ppEnabledExtensionNames(char const *const *const ppEnabledExtensionNames) {
96        info.ppEnabledExtensionNames = ppEnabledExtensionNames;
97
98        return *this;
99    }
100
101    operator VkInstanceCreateInfo const *() const { return &info; }
102
103    operator VkInstanceCreateInfo *() { return &info; }
104
105    VkInstanceCreateInfo info;
106};
107
108struct DeviceQueueCreateInfo {
109    DeviceQueueCreateInfo()
110        : info // MSVC can't handle list initialization, thus explicit construction herein.
111          (VkDeviceQueueCreateInfo{
112              VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, // sType
113              nullptr,                                    // pNext
114              0,                                          // flags
115              0,                                          // queueFamilyIndex
116              0,                                          // queueCount
117              nullptr                                     // pQueuePriorities
118          }) {}
119
120    DeviceQueueCreateInfo &sType(VkStructureType const &sType) {
121        info.sType = sType;
122
123        return *this;
124    }
125
126    DeviceQueueCreateInfo &pNext(void const *const pNext) {
127        info.pNext = pNext;
128
129        return *this;
130    }
131
132    DeviceQueueCreateInfo &flags(VkDeviceQueueCreateFlags const &flags) {
133        info.flags = flags;
134
135        return *this;
136    }
137
138    DeviceQueueCreateInfo &queueFamilyIndex(uint32_t const &queueFamilyIndex) {
139        info.queueFamilyIndex = queueFamilyIndex;
140
141        return *this;
142    }
143
144    DeviceQueueCreateInfo &queueCount(uint32_t const &queueCount) {
145        info.queueCount = queueCount;
146
147        return *this;
148    }
149
150    DeviceQueueCreateInfo &pQueuePriorities(float const *const pQueuePriorities) {
151        info.pQueuePriorities = pQueuePriorities;
152
153        return *this;
154    }
155
156    operator VkDeviceQueueCreateInfo() { return info; }
157
158    VkDeviceQueueCreateInfo info;
159};
160
161struct DeviceCreateInfo {
162    DeviceCreateInfo()
163        : info // MSVC can't handle list initialization, thus explicit construction herein.
164          (VkDeviceCreateInfo{
165              VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, // sType
166              nullptr,                              // pNext
167              0,                                    // flags
168              0,                                    // queueCreateInfoCount
169              nullptr,                              // pQueueCreateInfos
170              0,                                    // enabledLayerCount
171              nullptr,                              // ppEnabledLayerNames
172              0,                                    // enabledExtensionCount
173              nullptr,                              // ppEnabledExtensionNames
174              nullptr                               // pEnabledFeatures
175          }) {}
176
177    DeviceCreateInfo &sType(VkStructureType const &sType) {
178        info.sType = sType;
179
180        return *this;
181    }
182
183    DeviceCreateInfo &pNext(void const *const pNext) {
184        info.pNext = pNext;
185
186        return *this;
187    }
188
189    DeviceCreateInfo &flags(VkDeviceQueueCreateFlags const &flags) {
190        info.flags = flags;
191
192        return *this;
193    }
194
195    DeviceCreateInfo &queueCreateInfoCount(uint32_t const &queueCreateInfoCount) {
196        info.queueCreateInfoCount = queueCreateInfoCount;
197
198        return *this;
199    }
200
201    DeviceCreateInfo &pQueueCreateInfos(VkDeviceQueueCreateInfo const *const pQueueCreateInfos) {
202        info.pQueueCreateInfos = pQueueCreateInfos;
203
204        return *this;
205    }
206
207    DeviceCreateInfo &enabledLayerCount(uint32_t const &enabledLayerCount) {
208        info.enabledLayerCount = enabledLayerCount;
209
210        return *this;
211    }
212
213    DeviceCreateInfo &ppEnabledLayerNames(char const *const *const ppEnabledLayerNames) {
214        info.ppEnabledLayerNames = ppEnabledLayerNames;
215
216        return *this;
217    }
218
219    DeviceCreateInfo &enabledExtensionCount(uint32_t const &enabledExtensionCount) {
220        info.enabledExtensionCount = enabledExtensionCount;
221
222        return *this;
223    }
224
225    DeviceCreateInfo &ppEnabledExtensionNames(char const *const *const ppEnabledExtensionNames) {
226        info.ppEnabledExtensionNames = ppEnabledExtensionNames;
227
228        return *this;
229    }
230
231    DeviceCreateInfo &pEnabledFeatures(VkPhysicalDeviceFeatures const *const pEnabledFeatures) {
232        info.pEnabledFeatures = pEnabledFeatures;
233
234        return *this;
235    }
236
237    operator VkDeviceCreateInfo const *() const { return &info; }
238
239    operator VkDeviceCreateInfo *() { return &info; }
240
241    VkDeviceCreateInfo info;
242};
243}
244
245struct CommandLine : public ::testing::Test {
246    static void Initialize(int argc, char **argv) { arguments.assign(argv, argv + argc); };
247
248    static void SetUpTestCase(){};
249    static void TearDownTestCase(){};
250
251    static std::vector<std::string> arguments;
252};
253std::vector<std::string> CommandLine::arguments;
254
255struct EnumerateInstanceLayerProperties : public CommandLine {};
256struct EnumerateInstanceExtensionProperties : public CommandLine {};
257struct ImplicitLayer : public CommandLine {};
258
259// Test groups:
260// LX = lunar exchange
261// LVLGH = loader and validation github
262// LVLGL = lodaer and validation gitlab
263
264TEST(LX435, InstanceCreateInfoConst) {
265    VkInstanceCreateInfo const info = {VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, nullptr, 0, nullptr, 0, nullptr, 0, nullptr};
266
267    VkInstance instance = VK_NULL_HANDLE;
268    VkResult result = vkCreateInstance(&info, VK_NULL_HANDLE, &instance);
269    EXPECT_EQ(result, VK_SUCCESS);
270
271    vkDestroyInstance(instance, nullptr);
272}
273
274TEST(LX475, DestroyInstanceNullHandle) { vkDestroyInstance(VK_NULL_HANDLE, nullptr); }
275
276TEST(LX475, DestroyDeviceNullHandle) { vkDestroyDevice(VK_NULL_HANDLE, nullptr); }
277
278TEST(CreateInstance, ExtensionNotPresent) {
279    char const *const names[] = {"NotPresent"}; // Temporary required due to MSVC bug.
280    auto const info = VK::InstanceCreateInfo().enabledExtensionCount(1).ppEnabledExtensionNames(names);
281
282    VkInstance instance = VK_NULL_HANDLE;
283    VkResult result = vkCreateInstance(info, VK_NULL_HANDLE, &instance);
284    ASSERT_EQ(result, VK_ERROR_EXTENSION_NOT_PRESENT);
285
286    // It's not necessary to destroy the instance because it will not be created successfully.
287}
288
289TEST(CreateInstance, LayerNotPresent) {
290    char const *const names[] = {"NotPresent"}; // Temporary required due to MSVC bug.
291    auto const info = VK::InstanceCreateInfo().enabledLayerCount(1).ppEnabledLayerNames(names);
292
293    VkInstance instance = VK_NULL_HANDLE;
294    VkResult result = vkCreateInstance(info, VK_NULL_HANDLE, &instance);
295    ASSERT_EQ(result, VK_ERROR_LAYER_NOT_PRESENT);
296
297    // It's not necessary to destroy the instance because it will not be created successfully.
298}
299
300// Used by run_loader_tests.sh to test for layer insertion.
301TEST(CreateInstance, LayerPresent) {
302    char const *const names[] = {"VK_LAYER_LUNARG_parameter_validation"}; // Temporary required due to MSVC bug.
303    auto const info = VK::InstanceCreateInfo().enabledLayerCount(1).ppEnabledLayerNames(names);
304
305    VkInstance instance = VK_NULL_HANDLE;
306    VkResult result = vkCreateInstance(info, VK_NULL_HANDLE, &instance);
307    ASSERT_EQ(result, VK_SUCCESS);
308
309    vkDestroyInstance(instance, nullptr);
310}
311
312TEST(CreateDevice, ExtensionNotPresent) {
313    VkInstance instance = VK_NULL_HANDLE;
314    VkResult result = vkCreateInstance(VK::InstanceCreateInfo(), VK_NULL_HANDLE, &instance);
315    ASSERT_EQ(result, VK_SUCCESS);
316
317    uint32_t physicalCount = 0;
318    result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr);
319    ASSERT_EQ(result, VK_SUCCESS);
320    ASSERT_GT(physicalCount, 0u);
321
322    std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]);
323    result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get());
324    ASSERT_EQ(result, VK_SUCCESS);
325    ASSERT_GT(physicalCount, 0u);
326
327    for (uint32_t p = 0; p < physicalCount; ++p) {
328        uint32_t familyCount = 0;
329        vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, nullptr);
330        ASSERT_EQ(result, VK_SUCCESS);
331        ASSERT_GT(familyCount, 0u);
332
333        std::unique_ptr<VkQueueFamilyProperties[]> family(new VkQueueFamilyProperties[familyCount]);
334        vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, family.get());
335        ASSERT_EQ(result, VK_SUCCESS);
336        ASSERT_GT(familyCount, 0u);
337
338        for (uint32_t q = 0; q < familyCount; ++q) {
339            if (~family[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
340                continue;
341            }
342
343            float const priorities[] = {0.0f}; // Temporary required due to MSVC bug.
344            VkDeviceQueueCreateInfo const queueInfo[1]{
345                VK::DeviceQueueCreateInfo().queueFamilyIndex(q).queueCount(1).pQueuePriorities(priorities)};
346
347            char const *const names[] = {"NotPresent"}; // Temporary required due to MSVC bug.
348            auto const deviceInfo = VK::DeviceCreateInfo()
349                                        .queueCreateInfoCount(1)
350                                        .pQueueCreateInfos(queueInfo)
351                                        .enabledExtensionCount(1)
352                                        .ppEnabledExtensionNames(names);
353
354            VkDevice device;
355            result = vkCreateDevice(physical[p], deviceInfo, nullptr, &device);
356            ASSERT_EQ(result, VK_ERROR_EXTENSION_NOT_PRESENT);
357
358            // It's not necessary to destroy the device because it will not be created successfully.
359        }
360    }
361
362    vkDestroyInstance(instance, nullptr);
363}
364
365// LX535 / MI-76: Device layers are deprecated.
366// For backwards compatibility, they are allowed, but must be ignored.
367// Ensure that no errors occur if a bogus device layer list is passed to vkCreateDevice.
368TEST(CreateDevice, LayersNotPresent) {
369    VkInstance instance = VK_NULL_HANDLE;
370    VkResult result = vkCreateInstance(VK::InstanceCreateInfo(), VK_NULL_HANDLE, &instance);
371    ASSERT_EQ(result, VK_SUCCESS);
372
373    uint32_t physicalCount = 0;
374    result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr);
375    ASSERT_EQ(result, VK_SUCCESS);
376    ASSERT_GT(physicalCount, 0u);
377
378    std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]);
379    result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get());
380    ASSERT_EQ(result, VK_SUCCESS);
381    ASSERT_GT(physicalCount, 0u);
382
383    for (uint32_t p = 0; p < physicalCount; ++p) {
384        uint32_t familyCount = 0;
385        vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, nullptr);
386        ASSERT_EQ(result, VK_SUCCESS);
387        ASSERT_GT(familyCount, 0u);
388
389        std::unique_ptr<VkQueueFamilyProperties[]> family(new VkQueueFamilyProperties[familyCount]);
390        vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, family.get());
391        ASSERT_EQ(result, VK_SUCCESS);
392        ASSERT_GT(familyCount, 0u);
393
394        for (uint32_t q = 0; q < familyCount; ++q) {
395            if (~family[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
396                continue;
397            }
398
399            float const priorities[] = {0.0f}; // Temporary required due to MSVC bug.
400            VkDeviceQueueCreateInfo const queueInfo[1]{
401                VK::DeviceQueueCreateInfo().queueFamilyIndex(q).queueCount(1).pQueuePriorities(priorities)};
402
403            char const *const names[] = {"NotPresent"}; // Temporary required due to MSVC bug.
404            auto const deviceInfo = VK::DeviceCreateInfo()
405                                        .queueCreateInfoCount(1)
406                                        .pQueueCreateInfos(queueInfo)
407                                        .enabledLayerCount(1)
408                                        .ppEnabledLayerNames(names);
409
410            VkDevice device;
411            result = vkCreateDevice(physical[p], deviceInfo, nullptr, &device);
412            ASSERT_EQ(result, VK_SUCCESS);
413
414            vkDestroyDevice(device, nullptr);
415        }
416    }
417
418    vkDestroyInstance(instance, nullptr);
419}
420
421TEST_F(EnumerateInstanceLayerProperties, PropertyCountLessThanAvailable) {
422    uint32_t count = 0u;
423    VkResult result = vkEnumerateInstanceLayerProperties(&count, nullptr);
424    ASSERT_EQ(result, VK_SUCCESS);
425
426    // We need atleast two for the test to be relevant.
427    if (count < 2u) {
428        return;
429    }
430
431    std::unique_ptr<VkLayerProperties[]> properties(new VkLayerProperties[count]);
432    count = 1;
433    result = vkEnumerateInstanceLayerProperties(&count, properties.get());
434    ASSERT_EQ(result, VK_INCOMPLETE);
435}
436
437TEST(EnumerateDeviceLayerProperties, PropertyCountLessThanAvailable) {
438    VkInstance instance = VK_NULL_HANDLE;
439    VkResult result = vkCreateInstance(VK::InstanceCreateInfo(), VK_NULL_HANDLE, &instance);
440    ASSERT_EQ(result, VK_SUCCESS);
441
442    uint32_t physicalCount = 0;
443    result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr);
444    ASSERT_EQ(result, VK_SUCCESS);
445    ASSERT_GT(physicalCount, 0u);
446
447    std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]);
448    result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get());
449    ASSERT_EQ(result, VK_SUCCESS);
450    ASSERT_GT(physicalCount, 0u);
451
452    for (uint32_t p = 0; p < physicalCount; ++p) {
453        uint32_t count = 0u;
454        result = vkEnumerateDeviceLayerProperties(physical[p], &count, nullptr);
455        ASSERT_EQ(result, VK_SUCCESS);
456
457        // We need atleast two for the test to be relevant.
458        if (count < 2u) {
459            continue;
460        }
461
462        std::unique_ptr<VkLayerProperties[]> properties(new VkLayerProperties[count]);
463        count = 1;
464        result = vkEnumerateDeviceLayerProperties(physical[p], &count, properties.get());
465        ASSERT_EQ(result, VK_INCOMPLETE);
466    }
467
468    vkDestroyInstance(instance, nullptr);
469}
470
471TEST_F(EnumerateInstanceLayerProperties, Count) {
472    uint32_t count = 0u;
473    VkResult result = vkEnumerateInstanceLayerProperties(&count, nullptr);
474    ASSERT_EQ(result, VK_SUCCESS);
475
476    if (std::find(arguments.begin(), arguments.end(), "count") != arguments.end()) {
477        std::cout << "count=" << count << '\n';
478    }
479}
480
481TEST_F(EnumerateInstanceLayerProperties, OnePass) {
482    // Count required for this test.
483    if (std::find(arguments.begin(), arguments.end(), "count") == arguments.end()) {
484        return;
485    }
486
487    uint32_t count = std::stoul(arguments[2]);
488
489    std::unique_ptr<VkLayerProperties[]> properties(new VkLayerProperties[count]);
490    VkResult result = vkEnumerateInstanceLayerProperties(&count, properties.get());
491    ASSERT_EQ(result, VK_SUCCESS);
492
493    if (std::find(arguments.begin(), arguments.end(), "properties") != arguments.end()) {
494        for (uint32_t p = 0; p < count; ++p) {
495            std::cout << "properties[" << p << "] =" << ' ' << properties[p].layerName << ' ' << properties[p].specVersion << ' '
496                      << properties[p].implementationVersion << ' ' << properties[p].description << '\n';
497        }
498    }
499}
500
501TEST_F(EnumerateInstanceLayerProperties, TwoPass) {
502    uint32_t count = 0u;
503    VkResult result = vkEnumerateInstanceLayerProperties(&count, nullptr);
504    ASSERT_EQ(result, VK_SUCCESS);
505
506    std::unique_ptr<VkLayerProperties[]> properties(new VkLayerProperties[count]);
507    result = vkEnumerateInstanceLayerProperties(&count, properties.get());
508    ASSERT_EQ(result, VK_SUCCESS);
509
510    if (std::find(arguments.begin(), arguments.end(), "properties") != arguments.end()) {
511        for (uint32_t p = 0; p < count; ++p) {
512            std::cout << "properties[" << p << "] =" << ' ' << properties[p].layerName << ' ' << properties[p].specVersion << ' '
513                      << properties[p].implementationVersion << ' ' << properties[p].description << '\n';
514        }
515    }
516}
517
518TEST_F(EnumerateInstanceExtensionProperties, PropertyCountLessThanAvailable) {
519    uint32_t count = 0u;
520    VkResult result = vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr);
521    ASSERT_EQ(result, VK_SUCCESS);
522
523    // We need atleast two for the test to be relevant.
524    if (count < 2u) {
525        return;
526    }
527
528    std::unique_ptr<VkExtensionProperties[]> properties(new VkExtensionProperties[count]);
529    count = 1;
530    result = vkEnumerateInstanceExtensionProperties(nullptr, &count, properties.get());
531    ASSERT_EQ(result, VK_INCOMPLETE);
532}
533
534TEST(EnumerateDeviceExtensionProperties, PropertyCountLessThanAvailable) {
535    VkInstance instance = VK_NULL_HANDLE;
536    VkResult result = vkCreateInstance(VK::InstanceCreateInfo(), VK_NULL_HANDLE, &instance);
537    ASSERT_EQ(result, VK_SUCCESS);
538
539    uint32_t physicalCount = 0;
540    result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr);
541    ASSERT_EQ(result, VK_SUCCESS);
542    ASSERT_GT(physicalCount, 0u);
543
544    std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]);
545    result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get());
546    ASSERT_EQ(result, VK_SUCCESS);
547    ASSERT_GT(physicalCount, 0u);
548
549    for (uint32_t p = 0; p < physicalCount; ++p) {
550        uint32_t count = 0u;
551        result = vkEnumerateDeviceExtensionProperties(physical[p], nullptr, &count, nullptr);
552        ASSERT_EQ(result, VK_SUCCESS);
553
554        // We need atleast two for the test to be relevant.
555        if (count < 2u) {
556            continue;
557        }
558
559        std::unique_ptr<VkExtensionProperties[]> properties(new VkExtensionProperties[count]);
560        count = 1;
561        result = vkEnumerateDeviceExtensionProperties(physical[p], nullptr, &count, properties.get());
562        ASSERT_EQ(result, VK_INCOMPLETE);
563    }
564
565    vkDestroyInstance(instance, nullptr);
566}
567
568TEST_F(EnumerateInstanceExtensionProperties, Count) {
569    uint32_t count = 0u;
570    VkResult result = vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr);
571    ASSERT_EQ(result, VK_SUCCESS);
572
573    if (std::find(arguments.begin(), arguments.end(), "count") != arguments.end()) {
574        std::cout << "count=" << count << '\n';
575    }
576}
577
578TEST_F(EnumerateInstanceExtensionProperties, OnePass) {
579    // Count required for this test.
580    if (std::find(arguments.begin(), arguments.end(), "count") == arguments.end()) {
581        return;
582    }
583
584    uint32_t count = std::stoul(arguments[2]);
585
586    std::unique_ptr<VkExtensionProperties[]> properties(new VkExtensionProperties[count]);
587    VkResult result = vkEnumerateInstanceExtensionProperties(nullptr, &count, properties.get());
588    ASSERT_EQ(result, VK_SUCCESS);
589
590    if (std::find(arguments.begin(), arguments.end(), "properties") != arguments.end()) {
591        for (uint32_t p = 0; p < count; ++p) {
592            std::cout << "properties[" << p << "] =" << ' ' << properties[p].extensionName << ' ' << properties[p].specVersion
593                      << '\n';
594        }
595    }
596}
597
598TEST_F(EnumerateInstanceExtensionProperties, TwoPass) {
599    uint32_t count = 0u;
600    VkResult result = vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr);
601    ASSERT_EQ(result, VK_SUCCESS);
602
603    std::unique_ptr<VkExtensionProperties[]> properties(new VkExtensionProperties[count]);
604    result = vkEnumerateInstanceExtensionProperties(nullptr, &count, properties.get());
605    ASSERT_EQ(result, VK_SUCCESS);
606
607    if (std::find(arguments.begin(), arguments.end(), "properties") != arguments.end()) {
608        for (uint32_t p = 0; p < count; ++p) {
609            std::cout << "properties[" << p << "] =" << ' ' << properties[p].extensionName << ' ' << properties[p].specVersion
610                      << '\n';
611        }
612    }
613}
614
615TEST_F(EnumerateInstanceExtensionProperties, InstanceExtensionEnumerated) {
616    uint32_t count = 0u;
617    VkResult result = vkEnumerateInstanceExtensionProperties(nullptr, &count, nullptr);
618    ASSERT_EQ(result, VK_SUCCESS);
619
620    std::unique_ptr<VkExtensionProperties[]> properties(new VkExtensionProperties[count]);
621    result = vkEnumerateInstanceExtensionProperties(nullptr, &count, properties.get());
622    ASSERT_EQ(result, VK_SUCCESS);
623
624    ASSERT_NE(std::find_if(
625                  &properties[0], &properties[count],
626                  [](VkExtensionProperties const &properties) { return strcmp(properties.extensionName, "VK_KHR_surface") == 0; }),
627              &properties[count]);
628}
629
630TEST(EnumerateDeviceExtensionProperties, DeviceExtensionEnumerated) {
631    VkInstance instance = VK_NULL_HANDLE;
632    VkResult result = vkCreateInstance(VK::InstanceCreateInfo(), VK_NULL_HANDLE, &instance);
633    ASSERT_EQ(result, VK_SUCCESS);
634
635    uint32_t physicalCount = 0;
636    result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr);
637    ASSERT_EQ(result, VK_SUCCESS);
638    ASSERT_GT(physicalCount, 0u);
639
640    std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]);
641    result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get());
642    ASSERT_EQ(result, VK_SUCCESS);
643    ASSERT_GT(physicalCount, 0u);
644
645    for (uint32_t p = 0; p < physicalCount; ++p) {
646        uint32_t count = 0u;
647        result = vkEnumerateDeviceExtensionProperties(physical[p], nullptr, &count, nullptr);
648        ASSERT_EQ(result, VK_SUCCESS);
649
650        std::unique_ptr<VkExtensionProperties[]> properties(new VkExtensionProperties[count]);
651        result = vkEnumerateDeviceExtensionProperties(physical[p], nullptr, &count, properties.get());
652        ASSERT_EQ(result, VK_SUCCESS);
653
654        ASSERT_NE(std::find_if(&properties[0], &properties[count],
655                               [](VkExtensionProperties const &properties) {
656                                   return strcmp(properties.extensionName, "VK_KHR_swapchain") == 0;
657                               }),
658                  &properties[count]);
659    }
660
661    vkDestroyInstance(instance, nullptr);
662}
663
664TEST_F(ImplicitLayer, Present) {
665    auto const info = VK::InstanceCreateInfo();
666    VkInstance instance = VK_NULL_HANDLE;
667    VkResult result = vkCreateInstance(info, VK_NULL_HANDLE, &instance);
668    ASSERT_EQ(result, VK_SUCCESS);
669
670    vkDestroyInstance(instance, nullptr);
671}
672
673TEST(WrapObjects, Insert) {
674    VkInstance instance = VK_NULL_HANDLE;
675    VkResult result = vkCreateInstance(VK::InstanceCreateInfo(), VK_NULL_HANDLE, &instance);
676    ASSERT_EQ(result, VK_SUCCESS);
677
678    uint32_t physicalCount = 0;
679    result = vkEnumeratePhysicalDevices(instance, &physicalCount, nullptr);
680    ASSERT_EQ(result, VK_SUCCESS);
681    ASSERT_GT(physicalCount, 0u);
682
683    std::unique_ptr<VkPhysicalDevice[]> physical(new VkPhysicalDevice[physicalCount]);
684    result = vkEnumeratePhysicalDevices(instance, &physicalCount, physical.get());
685    ASSERT_EQ(result, VK_SUCCESS);
686    ASSERT_GT(physicalCount, 0u);
687
688    for (uint32_t p = 0; p < physicalCount; ++p) {
689        uint32_t familyCount = 0;
690        vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, nullptr);
691        ASSERT_EQ(result, VK_SUCCESS);
692        ASSERT_GT(familyCount, 0u);
693
694        std::unique_ptr<VkQueueFamilyProperties[]> family(new VkQueueFamilyProperties[familyCount]);
695        vkGetPhysicalDeviceQueueFamilyProperties(physical[p], &familyCount, family.get());
696        ASSERT_EQ(result, VK_SUCCESS);
697        ASSERT_GT(familyCount, 0u);
698
699        for (uint32_t q = 0; q < familyCount; ++q) {
700            if (~family[q].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
701                continue;
702            }
703
704            float const priorities[] = {0.0f}; // Temporary required due to MSVC bug.
705            VkDeviceQueueCreateInfo const queueInfo[1]{
706                VK::DeviceQueueCreateInfo().queueFamilyIndex(q).queueCount(1).pQueuePriorities(priorities)};
707
708            auto const deviceInfo = VK::DeviceCreateInfo().queueCreateInfoCount(1).pQueueCreateInfos(queueInfo);
709
710            VkDevice device;
711            result = vkCreateDevice(physical[p], deviceInfo, nullptr, &device);
712            ASSERT_EQ(result, VK_SUCCESS);
713
714            vkDestroyDevice(device, nullptr);
715        }
716    }
717
718    vkDestroyInstance(instance, nullptr);
719}
720
721int main(int argc, char **argv) {
722    int result;
723
724    ::testing::InitGoogleTest(&argc, argv);
725
726    if (argc > 0) {
727        CommandLine::Initialize(argc, argv);
728    }
729
730    result = RUN_ALL_TESTS();
731
732    return result;
733}
734