1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
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 Vulkan test case base classes
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktTestCase.hpp"
25
26 #include "vkRef.hpp"
27 #include "vkRefUtil.hpp"
28 #include "vkQueryUtil.hpp"
29 #include "vkDeviceUtil.hpp"
30 #include "vkMemUtil.hpp"
31 #include "vkPlatform.hpp"
32 #include "vkDebugReportUtil.hpp"
33
34 #include "tcuCommandLine.hpp"
35
36 #include "deSTLUtil.hpp"
37 #include "deMemory.h"
38
39 namespace vkt
40 {
41
42 // Default device utilities
43
44 using std::vector;
45 using std::string;
46 using namespace vk;
47
48 namespace
49 {
50
getValidationLayers(const vector<VkLayerProperties> & supportedLayers)51 vector<string> getValidationLayers (const vector<VkLayerProperties>& supportedLayers)
52 {
53 static const char* s_magicLayer = "VK_LAYER_LUNARG_standard_validation";
54 static const char* s_defaultLayers[] =
55 {
56 "VK_LAYER_GOOGLE_threading",
57 "VK_LAYER_LUNARG_parameter_validation",
58 "VK_LAYER_LUNARG_device_limits",
59 "VK_LAYER_LUNARG_object_tracker",
60 "VK_LAYER_LUNARG_image",
61 "VK_LAYER_LUNARG_core_validation",
62 "VK_LAYER_LUNARG_swapchain",
63 "VK_LAYER_GOOGLE_unique_objects"
64 };
65
66 vector<string> enabledLayers;
67
68 if (isLayerSupported(supportedLayers, RequiredLayer(s_magicLayer)))
69 enabledLayers.push_back(s_magicLayer);
70 else
71 {
72 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_defaultLayers); ++ndx)
73 {
74 if (isLayerSupported(supportedLayers, RequiredLayer(s_defaultLayers[ndx])))
75 enabledLayers.push_back(s_defaultLayers[ndx]);
76 }
77 }
78
79 return enabledLayers;
80 }
81
getValidationLayers(const PlatformInterface & vkp)82 vector<string> getValidationLayers (const PlatformInterface& vkp)
83 {
84 return getValidationLayers(enumerateInstanceLayerProperties(vkp));
85 }
86
getValidationLayers(const InstanceInterface & vki,VkPhysicalDevice physicalDevice)87 vector<string> getValidationLayers (const InstanceInterface& vki, VkPhysicalDevice physicalDevice)
88 {
89 return getValidationLayers(enumerateDeviceLayerProperties(vki, physicalDevice));
90 }
91
filterExtensions(const vector<VkExtensionProperties> & deviceExtensions)92 vector<string> filterExtensions(const vector<VkExtensionProperties>& deviceExtensions)
93 {
94 vector<string> enabledExtensions;
95 const char* extensionGroups[] =
96 {
97 "VK_KHR_",
98 "VK_EXT_",
99 "VK_KHX_"
100 };
101
102 for (size_t deviceExtNdx = 0; deviceExtNdx < deviceExtensions.size(); deviceExtNdx++)
103 {
104 for (int extGroupNdx = 0; extGroupNdx < DE_LENGTH_OF_ARRAY(extensionGroups); extGroupNdx++)
105 {
106 if (deStringBeginsWith(deviceExtensions[deviceExtNdx].extensionName, extensionGroups[extGroupNdx]))
107 enabledExtensions.push_back(deviceExtensions[deviceExtNdx].extensionName);
108 }
109 }
110
111 return enabledExtensions;
112 }
113
createInstance(const PlatformInterface & vkp,const vector<string> & enabledExtensions,const tcu::CommandLine & cmdLine)114 Move<VkInstance> createInstance (const PlatformInterface& vkp, const vector<string>& enabledExtensions, const tcu::CommandLine& cmdLine)
115 {
116 const bool isValidationEnabled = cmdLine.isValidationEnabled();
117 vector<string> enabledLayers;
118
119 if (isValidationEnabled)
120 {
121 if (!isDebugReportSupported(vkp))
122 TCU_THROW(NotSupportedError, "VK_EXT_debug_report is not supported");
123
124 enabledLayers = getValidationLayers(vkp);
125 if (enabledLayers.empty())
126 TCU_THROW(NotSupportedError, "No validation layers found");
127 }
128
129 return createDefaultInstance(vkp, enabledLayers, enabledExtensions);
130 }
131
findQueueFamilyIndexWithCaps(const InstanceInterface & vkInstance,VkPhysicalDevice physicalDevice,VkQueueFlags requiredCaps)132 static deUint32 findQueueFamilyIndexWithCaps (const InstanceInterface& vkInstance, VkPhysicalDevice physicalDevice, VkQueueFlags requiredCaps)
133 {
134 const vector<VkQueueFamilyProperties> queueProps = getPhysicalDeviceQueueFamilyProperties(vkInstance, physicalDevice);
135
136 for (size_t queueNdx = 0; queueNdx < queueProps.size(); queueNdx++)
137 {
138 if ((queueProps[queueNdx].queueFlags & requiredCaps) == requiredCaps)
139 return (deUint32)queueNdx;
140 }
141
142 TCU_THROW(NotSupportedError, "No matching queue found");
143 }
144
createDefaultDevice(const InstanceInterface & vki,VkPhysicalDevice physicalDevice,deUint32 queueIndex,const VkPhysicalDeviceFeatures2KHR & enabledFeatures,const vector<string> & enabledExtensions,const tcu::CommandLine & cmdLine)145 Move<VkDevice> createDefaultDevice (const InstanceInterface& vki,
146 VkPhysicalDevice physicalDevice,
147 deUint32 queueIndex,
148 const VkPhysicalDeviceFeatures2KHR& enabledFeatures,
149 const vector<string>& enabledExtensions,
150 const tcu::CommandLine& cmdLine)
151 {
152 VkDeviceQueueCreateInfo queueInfo;
153 VkDeviceCreateInfo deviceInfo;
154 vector<string> enabledLayers;
155 vector<const char*> layerPtrs;
156 vector<const char*> extensionPtrs;
157 const float queuePriority = 1.0f;
158
159 deMemset(&queueInfo, 0, sizeof(queueInfo));
160 deMemset(&deviceInfo, 0, sizeof(deviceInfo));
161
162 if (cmdLine.isValidationEnabled())
163 {
164 enabledLayers = getValidationLayers(vki, physicalDevice);
165 if (enabledLayers.empty())
166 TCU_THROW(NotSupportedError, "No validation layers found");
167 }
168
169 layerPtrs.resize(enabledLayers.size());
170
171 for (size_t ndx = 0; ndx < enabledLayers.size(); ++ndx)
172 layerPtrs[ndx] = enabledLayers[ndx].c_str();
173
174 extensionPtrs.resize(enabledExtensions.size());
175
176 for (size_t ndx = 0; ndx < enabledExtensions.size(); ++ndx)
177 extensionPtrs[ndx] = enabledExtensions[ndx].c_str();
178
179 // VK_KHR_get_physical_device_propeties2 is used if enabledFeatures.pNext != 0
180
181 queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
182 queueInfo.pNext = enabledFeatures.pNext ? &enabledFeatures : DE_NULL;
183 queueInfo.flags = (VkDeviceQueueCreateFlags)0u;
184 queueInfo.queueFamilyIndex = queueIndex;
185 queueInfo.queueCount = 1u;
186 queueInfo.pQueuePriorities = &queuePriority;
187
188 deviceInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
189 deviceInfo.pNext = DE_NULL;
190 deviceInfo.queueCreateInfoCount = 1u;
191 deviceInfo.pQueueCreateInfos = &queueInfo;
192 deviceInfo.enabledExtensionCount = (deUint32)extensionPtrs.size();
193 deviceInfo.ppEnabledExtensionNames = (extensionPtrs.empty() ? DE_NULL : &extensionPtrs[0]);
194 deviceInfo.enabledLayerCount = (deUint32)layerPtrs.size();
195 deviceInfo.ppEnabledLayerNames = (layerPtrs.empty() ? DE_NULL : &layerPtrs[0]);
196 deviceInfo.pEnabledFeatures = enabledFeatures.pNext ? DE_NULL : &enabledFeatures.features;
197
198 return createDevice(vki, physicalDevice, &deviceInfo);
199 };
200
isPhysicalDeviceFeatures2Supported(const vector<string> & instanceExtensions)201 bool isPhysicalDeviceFeatures2Supported (const vector<string>& instanceExtensions)
202 {
203 return de::contains(instanceExtensions.begin(), instanceExtensions.end(), "VK_KHR_get_physical_device_properties2");
204 }
205
206 struct DeviceFeatures
207 {
208 VkPhysicalDeviceFeatures2KHR coreFeatures;
209 VkPhysicalDeviceSamplerYcbcrConversionFeaturesKHR samplerYCbCrConversionFeatures;
210
DeviceFeaturesvkt::__anonf5dae72f0111::DeviceFeatures211 DeviceFeatures (const InstanceInterface& vki,
212 VkPhysicalDevice physicalDevice,
213 const vector<string>& instanceExtensions,
214 const vector<string>& deviceExtensions)
215 {
216 void** curExtPoint = &coreFeatures.pNext;
217
218 deMemset(&coreFeatures, 0, sizeof(coreFeatures));
219 deMemset(&samplerYCbCrConversionFeatures, 0, sizeof(samplerYCbCrConversionFeatures));
220
221 coreFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2_KHR;
222 samplerYCbCrConversionFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES_KHR;
223
224 if (isPhysicalDeviceFeatures2Supported(instanceExtensions))
225 {
226 if (de::contains(deviceExtensions.begin(), deviceExtensions.end(), "VK_KHR_sampler_ycbcr_conversion"))
227 {
228 *curExtPoint = &samplerYCbCrConversionFeatures;
229 curExtPoint = &samplerYCbCrConversionFeatures.pNext;
230 }
231
232 vki.getPhysicalDeviceFeatures2KHR(physicalDevice, &coreFeatures);
233 }
234 else
235 coreFeatures.features = getPhysicalDeviceFeatures(vki, physicalDevice);
236
237 // Disable robustness by default, as it has an impact on performance on some HW.
238 coreFeatures.features.robustBufferAccess = false;
239 }
240 };
241
242 } // anonymous
243
244 class DefaultDevice
245 {
246 public:
247 DefaultDevice (const PlatformInterface& vkPlatform, const tcu::CommandLine& cmdLine);
248 ~DefaultDevice (void);
249
getInstance(void) const250 VkInstance getInstance (void) const { return *m_instance; }
getInstanceInterface(void) const251 const InstanceInterface& getInstanceInterface (void) const { return m_instanceInterface; }
getInstanceExtensions(void) const252 const vector<string>& getInstanceExtensions (void) const { return m_instanceExtensions; }
253
getPhysicalDevice(void) const254 VkPhysicalDevice getPhysicalDevice (void) const { return m_physicalDevice; }
getDeviceFeatures(void) const255 const VkPhysicalDeviceFeatures& getDeviceFeatures (void) const { return m_deviceFeatures.coreFeatures.features; }
getDeviceFeatures2(void) const256 const VkPhysicalDeviceFeatures2KHR& getDeviceFeatures2 (void) const { return m_deviceFeatures.coreFeatures; }
getDevice(void) const257 VkDevice getDevice (void) const { return *m_device; }
getDeviceInterface(void) const258 const DeviceInterface& getDeviceInterface (void) const { return m_deviceInterface; }
getDeviceProperties(void) const259 const VkPhysicalDeviceProperties& getDeviceProperties (void) const { return m_deviceProperties; }
getDeviceExtensions(void) const260 const vector<string>& getDeviceExtensions (void) const { return m_deviceExtensions; }
261
getUniversalQueueFamilyIndex(void) const262 deUint32 getUniversalQueueFamilyIndex (void) const { return m_universalQueueFamilyIndex; }
263 VkQueue getUniversalQueue (void) const;
264
265 private:
266 static VkPhysicalDeviceFeatures filterDefaultDeviceFeatures (const VkPhysicalDeviceFeatures& deviceFeatures);
267
268 const vector<string> m_instanceExtensions;
269 const Unique<VkInstance> m_instance;
270 const InstanceDriver m_instanceInterface;
271
272 const VkPhysicalDevice m_physicalDevice;
273
274 const deUint32 m_universalQueueFamilyIndex;
275 const vector<string> m_deviceExtensions;
276 const DeviceFeatures m_deviceFeatures;
277 const VkPhysicalDeviceProperties m_deviceProperties;
278
279 const Unique<VkDevice> m_device;
280 const DeviceDriver m_deviceInterface;
281 };
282
DefaultDevice(const PlatformInterface & vkPlatform,const tcu::CommandLine & cmdLine)283 DefaultDevice::DefaultDevice (const PlatformInterface& vkPlatform, const tcu::CommandLine& cmdLine)
284 : m_instanceExtensions (filterExtensions(enumerateInstanceExtensionProperties(vkPlatform, DE_NULL)))
285 , m_instance (createInstance(vkPlatform, m_instanceExtensions, cmdLine))
286 , m_instanceInterface (vkPlatform, *m_instance)
287 , m_physicalDevice (chooseDevice(m_instanceInterface, *m_instance, cmdLine))
288 , m_universalQueueFamilyIndex (findQueueFamilyIndexWithCaps(m_instanceInterface, m_physicalDevice, VK_QUEUE_GRAPHICS_BIT|VK_QUEUE_COMPUTE_BIT))
289 , m_deviceExtensions (filterExtensions(enumerateDeviceExtensionProperties(m_instanceInterface, m_physicalDevice, DE_NULL)))
290 , m_deviceFeatures (m_instanceInterface, m_physicalDevice, m_instanceExtensions, m_deviceExtensions)
291 , m_deviceProperties (getPhysicalDeviceProperties(m_instanceInterface, m_physicalDevice))
292 , m_device (createDefaultDevice(m_instanceInterface,
293 m_physicalDevice,
294 m_universalQueueFamilyIndex,
295 m_deviceFeatures.coreFeatures,
296 m_deviceExtensions,
297 cmdLine))
298 , m_deviceInterface (m_instanceInterface, *m_device)
299 {
300 }
301
~DefaultDevice(void)302 DefaultDevice::~DefaultDevice (void)
303 {
304 }
305
getUniversalQueue(void) const306 VkQueue DefaultDevice::getUniversalQueue (void) const
307 {
308 return getDeviceQueue(m_deviceInterface, *m_device, m_universalQueueFamilyIndex, 0);
309 }
310
311 namespace
312 {
313
314 // Allocator utilities
315
createAllocator(DefaultDevice * device)316 vk::Allocator* createAllocator (DefaultDevice* device)
317 {
318 const VkPhysicalDeviceMemoryProperties memoryProperties = vk::getPhysicalDeviceMemoryProperties(device->getInstanceInterface(), device->getPhysicalDevice());
319
320 // \todo [2015-07-24 jarkko] support allocator selection/configuration from command line (or compile time)
321 return new SimpleAllocator(device->getDeviceInterface(), device->getDevice(), memoryProperties);
322 }
323
324 } // anonymous
325
326 // Context
327
Context(tcu::TestContext & testCtx,const vk::PlatformInterface & platformInterface,vk::ProgramCollection<vk::ProgramBinary> & progCollection)328 Context::Context (tcu::TestContext& testCtx,
329 const vk::PlatformInterface& platformInterface,
330 vk::ProgramCollection<vk::ProgramBinary>& progCollection)
331 : m_testCtx (testCtx)
332 , m_platformInterface (platformInterface)
333 , m_progCollection (progCollection)
334 , m_device (new DefaultDevice(m_platformInterface, testCtx.getCommandLine()))
335 , m_allocator (createAllocator(m_device.get()))
336 {
337 }
338
~Context(void)339 Context::~Context (void)
340 {
341 }
342
getInstanceExtensions(void) const343 const vector<string>& Context::getInstanceExtensions (void) const { return m_device->getInstanceExtensions(); }
getInstance(void) const344 vk::VkInstance Context::getInstance (void) const { return m_device->getInstance(); }
getInstanceInterface(void) const345 const vk::InstanceInterface& Context::getInstanceInterface (void) const { return m_device->getInstanceInterface(); }
getPhysicalDevice(void) const346 vk::VkPhysicalDevice Context::getPhysicalDevice (void) const { return m_device->getPhysicalDevice(); }
getDeviceFeatures(void) const347 const vk::VkPhysicalDeviceFeatures& Context::getDeviceFeatures (void) const { return m_device->getDeviceFeatures(); }
getDeviceFeatures2(void) const348 const vk::VkPhysicalDeviceFeatures2KHR& Context::getDeviceFeatures2 (void) const { return m_device->getDeviceFeatures2(); }
getDeviceProperties(void) const349 const vk::VkPhysicalDeviceProperties& Context::getDeviceProperties (void) const { return m_device->getDeviceProperties(); }
getDeviceExtensions(void) const350 const vector<string>& Context::getDeviceExtensions (void) const { return m_device->getDeviceExtensions(); }
getDevice(void) const351 vk::VkDevice Context::getDevice (void) const { return m_device->getDevice(); }
getDeviceInterface(void) const352 const vk::DeviceInterface& Context::getDeviceInterface (void) const { return m_device->getDeviceInterface(); }
getUniversalQueueFamilyIndex(void) const353 deUint32 Context::getUniversalQueueFamilyIndex (void) const { return m_device->getUniversalQueueFamilyIndex(); }
getUniversalQueue(void) const354 vk::VkQueue Context::getUniversalQueue (void) const { return m_device->getUniversalQueue(); }
getDefaultAllocator(void) const355 vk::Allocator& Context::getDefaultAllocator (void) const { return *m_allocator; }
356
357 // TestCase
358
initPrograms(SourceCollections &) const359 void TestCase::initPrograms (SourceCollections&) const
360 {
361 }
362
363 } // vkt
364