1 /*-------------------------------------------------------------------------
2 * Vulkan CTS Framework
3 * --------------------
4 *
5 * Copyright (c) 2015 Google Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Instance and device initialization utilities.
22 *//*--------------------------------------------------------------------*/
23
24 #include "deSTLUtil.hpp"
25 #include "vkDeviceUtil.hpp"
26 #include "vkQueryUtil.hpp"
27 #include "vkRefUtil.hpp"
28 #include "vkApiVersion.hpp"
29 #include "vkDebugReportUtil.hpp"
30
31 #include "tcuCommandLine.hpp"
32
33 #include "qpInfo.h"
34
35 #ifdef CTS_USES_VULKANSC
36 #include "vkAppParamsUtil.hpp"
37 #endif // CTS_USES_VULKANSC
38
39 namespace vk
40 {
41
42 using std::string;
43 using std::vector;
44
createDefaultInstance(const PlatformInterface & vkPlatform,uint32_t apiVersion,const vector<string> & enabledLayers,const vector<string> & enabledExtensions,const tcu::CommandLine & cmdLine,DebugReportRecorder * recorder,const VkAllocationCallbacks * pAllocator)45 Move<VkInstance> createDefaultInstance(const PlatformInterface &vkPlatform, uint32_t apiVersion,
46 const vector<string> &enabledLayers, const vector<string> &enabledExtensions,
47 const tcu::CommandLine &cmdLine,
48 #ifndef CTS_USES_VULKANSC
49 DebugReportRecorder *recorder,
50 #endif // CTS_USES_VULKANSC
51 const VkAllocationCallbacks *pAllocator)
52 {
53 bool validationEnabled = (!enabledLayers.empty());
54 vector<string> actualExtensions = enabledExtensions;
55
56 // Enumerate once, pass it in to the various functions that require the list of available extensions
57 vector<vk::VkExtensionProperties> availableExtensions = enumerateInstanceExtensionProperties(vkPlatform, DE_NULL);
58
59 #ifndef CTS_USES_VULKANSC
60 if (validationEnabled)
61 {
62 // Make sure the debug report extension is enabled when validation is enabled.
63 if (!isExtensionStructSupported(availableExtensions, RequiredExtension("VK_EXT_debug_report")))
64 TCU_THROW(NotSupportedError, "VK_EXT_debug_report is not supported");
65
66 if (!de::contains(begin(actualExtensions), end(actualExtensions), "VK_EXT_debug_report"))
67 actualExtensions.push_back("VK_EXT_debug_report");
68
69 DE_ASSERT(recorder);
70 }
71
72 // Make sure portability enumeration is enabled whenever it is available
73 bool portability_enumeration_available =
74 isExtensionStructSupported(availableExtensions, RequiredExtension("VK_KHR_portability_enumeration"));
75 if (portability_enumeration_available)
76 {
77 actualExtensions.push_back("VK_KHR_portability_enumeration");
78 }
79
80 #endif // CTS_USES_VULKANSC
81
82 vector<const char *> layerNamePtrs(enabledLayers.size());
83 vector<const char *> extensionNamePtrs(actualExtensions.size());
84
85 for (size_t ndx = 0; ndx < enabledLayers.size(); ++ndx)
86 layerNamePtrs[ndx] = enabledLayers[ndx].c_str();
87
88 for (size_t ndx = 0; ndx < actualExtensions.size(); ++ndx)
89 extensionNamePtrs[ndx] = actualExtensions[ndx].c_str();
90
91 #ifdef CTS_USES_VULKANSC
92 vector<VkApplicationParametersEXT> appParams;
93 const bool hasAppParams = readApplicationParameters(appParams, cmdLine, true);
94 #else
95 DE_UNREF(cmdLine);
96 #endif // CTS_USES_VULKANSC
97
98 const struct VkApplicationInfo appInfo = {
99 VK_STRUCTURE_TYPE_APPLICATION_INFO,
100 #ifdef CTS_USES_VULKANSC
101 hasAppParams ? &appParams[0] : DE_NULL,
102 #else
103 DE_NULL,
104 #endif // CTS_USES_VULKANSC
105 "deqp", // pAppName
106 qpGetReleaseId(), // appVersion
107 "deqp", // pEngineName
108 qpGetReleaseId(), // engineVersion
109 apiVersion // apiVersion
110 };
111
112 #ifndef CTS_USES_VULKANSC
113 const VkDebugReportCallbackCreateInfoEXT callbackInfo =
114 (validationEnabled ? recorder->makeCreateInfo() : initVulkanStructure());
115 #endif // CTS_USES_VULKANSC
116
117 const struct VkInstanceCreateInfo instanceInfo = {
118 VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
119 #ifndef CTS_USES_VULKANSC
120 (validationEnabled ? &callbackInfo : nullptr),
121 (VkInstanceCreateFlags)(portability_enumeration_available ? VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR :
122 0),
123 #else
124 nullptr,
125 (VkInstanceCreateFlags)0,
126 #endif // CTS_USES_VULKANSC
127 &appInfo,
128 (uint32_t)layerNamePtrs.size(),
129 (validationEnabled ? layerNamePtrs.data() : nullptr),
130 (uint32_t)extensionNamePtrs.size(),
131 (extensionNamePtrs.empty() ? nullptr : extensionNamePtrs.data()),
132 };
133
134 return createInstance(vkPlatform, &instanceInfo, pAllocator);
135 }
136
createDefaultInstance(const PlatformInterface & vkPlatform,uint32_t apiVersion,const tcu::CommandLine & cmdLine)137 Move<VkInstance> createDefaultInstance(const PlatformInterface &vkPlatform, uint32_t apiVersion,
138 const tcu::CommandLine &cmdLine)
139 {
140 #ifndef CTS_USES_VULKANSC
141 return createDefaultInstance(vkPlatform, apiVersion, vector<string>(), vector<string>(), cmdLine, nullptr, nullptr);
142 #else
143 return createDefaultInstance(vkPlatform, apiVersion, vector<string>(), vector<string>(), cmdLine, nullptr);
144 #endif
145 }
146
chooseDeviceIndex(const InstanceInterface & vkInstance,const VkInstance instance,const tcu::CommandLine & cmdLine)147 uint32_t chooseDeviceIndex(const InstanceInterface &vkInstance, const VkInstance instance,
148 const tcu::CommandLine &cmdLine)
149 {
150 const vector<VkPhysicalDevice> devices = enumeratePhysicalDevices(vkInstance, instance);
151
152 if (devices.empty())
153 TCU_THROW(NotSupportedError, "No Vulkan devices available");
154
155 const uint32_t deviceIdFromCmdLine = cmdLine.getVKDeviceId();
156 if (!de::inBounds(deviceIdFromCmdLine, 0u, static_cast<uint32_t>(devices.size() + 1)))
157 TCU_THROW(InternalError, "Invalid --deqp-vk-device-id");
158
159 if (deviceIdFromCmdLine > 0)
160 return deviceIdFromCmdLine - 1u;
161
162 uint32_t maxReportedApiVersion = 0u;
163 uint32_t ndxOfMaximumVersion = 0u;
164
165 for (uint32_t deviceNdx = 0u; deviceNdx < devices.size(); ++deviceNdx)
166 {
167 const VkPhysicalDeviceProperties props = getPhysicalDeviceProperties(vkInstance, devices[deviceNdx]);
168
169 if (props.apiVersion > maxReportedApiVersion)
170 {
171 maxReportedApiVersion = props.apiVersion;
172 ndxOfMaximumVersion = deviceNdx;
173 }
174 }
175
176 return ndxOfMaximumVersion;
177 }
178
chooseDevice(const InstanceInterface & vkInstance,const VkInstance instance,const tcu::CommandLine & cmdLine)179 VkPhysicalDevice chooseDevice(const InstanceInterface &vkInstance, const VkInstance instance,
180 const tcu::CommandLine &cmdLine)
181 {
182 const vector<VkPhysicalDevice> devices = enumeratePhysicalDevices(vkInstance, instance);
183
184 if (devices.empty())
185 TCU_THROW(NotSupportedError, "No Vulkan devices available");
186
187 const size_t deviceId = chooseDeviceIndex(vkInstance, instance, cmdLine);
188 return devices[deviceId];
189 }
190
191 } // namespace vk
192