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: Chia-I Wu <olvaffe@gmail.com>
26 * Author: Chris Forbes <chrisf@ijw.co.nz>
27 * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
28 * Author: Mark Lobodzinski <mark@lunarg.com>
29 * Author: Mike Stroyan <mike@LunarG.com>
30 * Author: Tobin Ehlis <tobine@google.com>
31 * Author: Tony Barbour <tony@LunarG.com>
32 */
33
34#include "test_common.h"
35#include "vktestbinding.h"
36#include "test_environment.h"
37
38#if defined(NDEBUG) && defined(__GNUC__)
39#define U_ASSERT_ONLY __attribute__((unused))
40#else
41#define U_ASSERT_ONLY
42#endif
43
44#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
45
46namespace vk_testing {
47
48Environment::Environment() : default_dev_(0) {
49    app_.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
50    app_.pApplicationName = "vk_testing";
51    app_.applicationVersion = 1;
52    app_.pEngineName = "vk_testing";
53    app_.engineVersion = 1;
54    app_.apiVersion = VK_API_VERSION_1_0;
55    app_.pNext = NULL;
56}
57
58bool Environment::parse_args(int argc, char **argv) {
59    int i;
60
61    for (i = 1; i < argc; i++) {
62#define ARG(name) (strcmp(argv[i], name) == 0)
63#define ARG_P(name) (i < argc - 1 && ARG(name))
64        if (ARG_P("--gpu")) {
65            default_dev_ = atoi(argv[++i]);
66        } else {
67            break;
68        }
69#undef ARG
70#undef ARG_P
71    }
72
73    if (i < argc) {
74        std::cout << "invalid argument: " << argv[i] << "\n\n"
75                  << "Usage: " << argv[0] << " <options>\n\n"
76                  << "Options:\n"
77                     "  --gpu <n>  Use GPU<n> as the default GPU\n";
78
79        return false;
80    }
81
82    return true;
83}
84
85void Environment::SetUp() {
86
87    uint32_t count;
88    VkResult U_ASSERT_ONLY err;
89    VkInstanceCreateInfo inst_info = {};
90    std::vector<VkExtensionProperties> instance_extensions;
91    std::vector<VkExtensionProperties> device_extensions;
92
93    std::vector<const char *> instance_extension_names;
94    std::vector<const char *> device_extension_names;
95    std::vector<const char *> device_layer_names;
96
97    instance_extension_names.push_back(VK_KHR_SURFACE_EXTENSION_NAME);
98    device_extension_names.push_back(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
99
100    VkBool32 extFound;
101
102    instance_extensions = vk_testing::GetGlobalExtensions();
103
104    for (uint32_t i = 0; i < instance_extension_names.size(); i++) {
105        extFound = 0;
106        for (uint32_t j = 0; j < instance_extensions.size(); j++) {
107            if (!strcmp(instance_extension_names[i],
108                        instance_extensions[j].extensionName)) {
109                extFound = 1;
110            }
111        }
112        ASSERT_EQ(extFound, 1) << "ERROR: Cannot find extension named "
113                               << instance_extension_names[i]
114                               << " which is necessary to pass this test";
115    }
116    inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
117    inst_info.pNext = NULL;
118    inst_info.pApplicationInfo = &app_;
119    inst_info.enabledExtensionCount = instance_extension_names.size();
120    inst_info.ppEnabledExtensionNames =
121        (instance_extension_names.size()) ? &instance_extension_names[0] : NULL;
122    inst_info.enabledLayerCount = 0;
123    inst_info.ppEnabledLayerNames = NULL;
124    err = vkCreateInstance(&inst_info, NULL, &inst);
125    ASSERT_EQ(VK_SUCCESS, err);
126    err = vkEnumeratePhysicalDevices(inst, &count, NULL);
127    ASSERT_EQ(VK_SUCCESS, err);
128    ASSERT_LE(count, ARRAY_SIZE(gpus));
129    err = vkEnumeratePhysicalDevices(inst, &count, gpus);
130    ASSERT_EQ(VK_SUCCESS, err);
131    ASSERT_GT(count, default_dev_);
132
133    vk_testing::PhysicalDevice phys_dev(gpus[0]);
134    device_extensions = phys_dev.extensions();
135
136    for (uint32_t i = 0; i < device_extension_names.size(); i++) {
137        extFound = 0;
138        for (uint32_t j = 0; j < device_extensions.size(); j++) {
139            if (!strcmp(device_extension_names[i],
140                        device_extensions[j].extensionName)) {
141                extFound = 1;
142            }
143        }
144        ASSERT_EQ(extFound, 1) << "ERROR: Cannot find extension named "
145                               << device_extension_names[i]
146                               << " which is necessary to pass this test";
147    }
148
149    devs_.reserve(count);
150    for (uint32_t i = 0; i < count; i++) {
151        devs_.push_back(new Device(gpus[i]));
152        if (i == default_dev_) {
153            devs_[i]->init(device_layer_names, device_extension_names);
154            ASSERT_NE(true, devs_[i]->graphics_queues().empty());
155        }
156    }
157}
158
159void Environment::TearDown() {
160    // destroy devices first
161    for (std::vector<Device *>::iterator it = devs_.begin(); it != devs_.end();
162         it++)
163        delete *it;
164    devs_.clear();
165
166    if (inst)
167        vkDestroyInstance(inst, NULL);
168}
169} // vk_testing namespace
170