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 
46 namespace vk_testing {
47 
Environment()48 Environment::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 
parse_args(int argc,char ** argv)58 bool 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 
SetUp()85 void 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 
TearDown()159 void 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