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 #include <set> 40 41 namespace vkt 42 { 43 44 // Default device utilities 45 46 using std::vector; 47 using std::string; 48 using std::set; 49 using namespace vk; 50 51 namespace 52 { 53 54 vector<string> getValidationLayers (const vector<VkLayerProperties>& supportedLayers) 55 { 56 static const char* s_magicLayer = "VK_LAYER_LUNARG_standard_validation"; 57 static const char* s_defaultLayers[] = 58 { 59 "VK_LAYER_GOOGLE_threading", 60 "VK_LAYER_LUNARG_parameter_validation", 61 "VK_LAYER_LUNARG_device_limits", 62 "VK_LAYER_LUNARG_object_tracker", 63 "VK_LAYER_LUNARG_image", 64 "VK_LAYER_LUNARG_core_validation", 65 "VK_LAYER_LUNARG_swapchain", 66 "VK_LAYER_GOOGLE_unique_objects" 67 }; 68 69 vector<string> enabledLayers; 70 71 if (isLayerSupported(supportedLayers, RequiredLayer(s_magicLayer))) 72 enabledLayers.push_back(s_magicLayer); 73 else 74 { 75 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_defaultLayers); ++ndx) 76 { 77 if (isLayerSupported(supportedLayers, RequiredLayer(s_defaultLayers[ndx]))) 78 enabledLayers.push_back(s_defaultLayers[ndx]); 79 } 80 } 81 82 return enabledLayers; 83 } 84 85 vector<string> getValidationLayers (const PlatformInterface& vkp) 86 { 87 return getValidationLayers(enumerateInstanceLayerProperties(vkp)); 88 } 89 90 vector<string> getValidationLayers (const InstanceInterface& vki, VkPhysicalDevice physicalDevice) 91 { 92 return getValidationLayers(enumerateDeviceLayerProperties(vki, physicalDevice)); 93 } 94 95 vector<string> filterExtensions (const vector<VkExtensionProperties>& extensions) 96 { 97 vector<string> enabledExtensions; 98 const char* extensionGroups[] = 99 { 100 "VK_KHR_", 101 "VK_EXT_", 102 "VK_KHX_" 103 }; 104 105 for (size_t extNdx = 0; extNdx < extensions.size(); extNdx++) 106 { 107 for (int extGroupNdx = 0; extGroupNdx < DE_LENGTH_OF_ARRAY(extensionGroups); extGroupNdx++) 108 { 109 if (deStringBeginsWith(extensions[extNdx].extensionName, extensionGroups[extGroupNdx])) 110 enabledExtensions.push_back(extensions[extNdx].extensionName); 111 } 112 } 113 114 return enabledExtensions; 115 } 116 117 vector<string> addExtensions (const vector<string>& a, const vector<const char*>& b) 118 { 119 vector<string> res (a); 120 121 for (vector<const char*>::const_iterator bIter = b.begin(); bIter != b.end(); ++bIter) 122 { 123 if (!de::contains(res.begin(), res.end(), string(*bIter))) 124 res.push_back(string(*bIter)); 125 } 126 127 return res; 128 } 129 130 vector<string> removeExtensions (const vector<string>& a, const vector<const char*>& b) 131 { 132 vector<string> res; 133 set<string> removeExts (b.begin(), b.end()); 134 135 for (vector<string>::const_iterator aIter = a.begin(); aIter != a.end(); ++aIter) 136 { 137 if (!de::contains(removeExts, *aIter)) 138 res.push_back(*aIter); 139 } 140 141 return res; 142 } 143 144 vector<string> addCoreInstanceExtensions (const vector<string>& extensions, deUint32 instanceVersion) 145 { 146 vector<const char*> coreExtensions; 147 getCoreInstanceExtensions(instanceVersion, coreExtensions); 148 return addExtensions(extensions, coreExtensions); 149 } 150 151 vector<string> addCoreDeviceExtensions(const vector<string>& extensions, deUint32 instanceVersion) 152 { 153 vector<const char*> coreExtensions; 154 getCoreDeviceExtensions(instanceVersion, coreExtensions); 155 return addExtensions(extensions, coreExtensions); 156 } 157 158 deUint32 getTargetInstanceVersion (const PlatformInterface& vkp) 159 { 160 deUint32 version = pack(ApiVersion(1, 0, 0)); 161 if (vkp.enumerateInstanceVersion(&version) != VK_SUCCESS) 162 TCU_THROW(InternalError, "Enumerate instance version error"); 163 return version; 164 } 165 166 std::pair<deUint32, deUint32> determineDeviceVersions(const PlatformInterface& vkp, deUint32 apiVersion, const tcu::CommandLine& cmdLine) 167 { 168 Move<VkInstance> preinstance = createDefaultInstance(vkp, apiVersion); 169 InstanceDriver preinterface (vkp, preinstance.get()); 170 171 const vector<VkPhysicalDevice> devices = enumeratePhysicalDevices(preinterface, preinstance.get()); 172 deUint32 lowestDeviceVersion = 0xFFFFFFFFu; 173 for (deUint32 deviceNdx = 0u; deviceNdx < devices.size(); ++deviceNdx) 174 { 175 const VkPhysicalDeviceProperties props = getPhysicalDeviceProperties(preinterface, devices[deviceNdx]); 176 if (props.apiVersion < lowestDeviceVersion) 177 lowestDeviceVersion = props.apiVersion; 178 } 179 180 const vk::VkPhysicalDevice choosenDevice = chooseDevice(preinterface, *preinstance, cmdLine); 181 const VkPhysicalDeviceProperties props = getPhysicalDeviceProperties(preinterface, choosenDevice); 182 const deUint32 choosenDeviceVersion = props.apiVersion; 183 184 return std::make_pair(choosenDeviceVersion, lowestDeviceVersion); 185 } 186 187 188 Move<VkInstance> createInstance (const PlatformInterface& vkp, deUint32 apiVersion, const vector<string>& enabledExtensions, const tcu::CommandLine& cmdLine) 189 { 190 const bool isValidationEnabled = cmdLine.isValidationEnabled(); 191 vector<string> enabledLayers; 192 193 // \note Extensions in core are not explicitly enabled even though 194 // they are in the extension list advertised to tests. 195 vector<const char*> coreExtensions; 196 getCoreInstanceExtensions(apiVersion, coreExtensions); 197 vector<string> nonCoreExtensions (removeExtensions(enabledExtensions, coreExtensions)); 198 199 if (isValidationEnabled) 200 { 201 if (!isDebugReportSupported(vkp)) 202 TCU_THROW(NotSupportedError, "VK_EXT_debug_report is not supported"); 203 204 enabledLayers = getValidationLayers(vkp); 205 if (enabledLayers.empty()) 206 TCU_THROW(NotSupportedError, "No validation layers found"); 207 } 208 209 return createDefaultInstance(vkp, apiVersion, enabledLayers, nonCoreExtensions); 210 } 211 212 static deUint32 findQueueFamilyIndexWithCaps (const InstanceInterface& vkInstance, VkPhysicalDevice physicalDevice, VkQueueFlags requiredCaps) 213 { 214 const vector<VkQueueFamilyProperties> queueProps = getPhysicalDeviceQueueFamilyProperties(vkInstance, physicalDevice); 215 216 for (size_t queueNdx = 0; queueNdx < queueProps.size(); queueNdx++) 217 { 218 if ((queueProps[queueNdx].queueFlags & requiredCaps) == requiredCaps) 219 return (deUint32)queueNdx; 220 } 221 222 TCU_THROW(NotSupportedError, "No matching queue found"); 223 } 224 225 Move<VkDevice> createDefaultDevice (const InstanceInterface& vki, 226 VkPhysicalDevice physicalDevice, 227 const deUint32 apiVersion, 228 deUint32 queueIndex, 229 const VkPhysicalDeviceFeatures2& enabledFeatures, 230 const vector<string>& enabledExtensions, 231 const tcu::CommandLine& cmdLine) 232 { 233 VkDeviceQueueCreateInfo queueInfo; 234 VkDeviceCreateInfo deviceInfo; 235 vector<string> enabledLayers; 236 vector<const char*> layerPtrs; 237 vector<const char*> extensionPtrs; 238 const float queuePriority = 1.0f; 239 240 deMemset(&queueInfo, 0, sizeof(queueInfo)); 241 deMemset(&deviceInfo, 0, sizeof(deviceInfo)); 242 243 if (cmdLine.isValidationEnabled()) 244 { 245 enabledLayers = getValidationLayers(vki, physicalDevice); 246 if (enabledLayers.empty()) 247 TCU_THROW(NotSupportedError, "No validation layers found"); 248 } 249 250 layerPtrs.resize(enabledLayers.size()); 251 252 for (size_t ndx = 0; ndx < enabledLayers.size(); ++ndx) 253 layerPtrs[ndx] = enabledLayers[ndx].c_str(); 254 255 // \note Extensions in core are not explicitly enabled even though 256 // they are in the extension list advertised to tests. 257 vector<const char*> coreExtensions; 258 getCoreDeviceExtensions(apiVersion, coreExtensions); 259 vector<string> nonCoreExtensions(removeExtensions(enabledExtensions, coreExtensions)); 260 261 extensionPtrs.resize(nonCoreExtensions.size()); 262 263 for (size_t ndx = 0; ndx < nonCoreExtensions.size(); ++ndx) 264 extensionPtrs[ndx] = nonCoreExtensions[ndx].c_str(); 265 266 // VK_KHR_get_physical_device_propeties2 is used if enabledFeatures.pNext != 0 267 268 queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; 269 queueInfo.pNext = DE_NULL; 270 queueInfo.flags = (VkDeviceQueueCreateFlags)0u; 271 queueInfo.queueFamilyIndex = queueIndex; 272 queueInfo.queueCount = 1u; 273 queueInfo.pQueuePriorities = &queuePriority; 274 275 deviceInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; 276 deviceInfo.pNext = enabledFeatures.pNext ? &enabledFeatures : DE_NULL; 277 deviceInfo.queueCreateInfoCount = 1u; 278 deviceInfo.pQueueCreateInfos = &queueInfo; 279 deviceInfo.enabledExtensionCount = (deUint32)extensionPtrs.size(); 280 deviceInfo.ppEnabledExtensionNames = (extensionPtrs.empty() ? DE_NULL : &extensionPtrs[0]); 281 deviceInfo.enabledLayerCount = (deUint32)layerPtrs.size(); 282 deviceInfo.ppEnabledLayerNames = (layerPtrs.empty() ? DE_NULL : &layerPtrs[0]); 283 deviceInfo.pEnabledFeatures = enabledFeatures.pNext ? DE_NULL : &enabledFeatures.features; 284 285 return createDevice(vki, physicalDevice, &deviceInfo); 286 }; 287 288 bool isPhysicalDeviceFeatures2Supported (const deUint32 version, const vector<string>& instanceExtensions) 289 { 290 return isInstanceExtensionSupported(version, instanceExtensions, "VK_KHR_get_physical_device_properties2"); 291 } 292 293 class DeviceFeatures 294 { 295 public: 296 VkPhysicalDeviceFeatures2 coreFeatures; 297 VkPhysicalDeviceSamplerYcbcrConversionFeatures samplerYCbCrConversionFeatures; 298 299 DeviceFeatures (const InstanceInterface& vki, 300 const deUint32 apiVersion, 301 const VkPhysicalDevice& physicalDevice, 302 const vector<string>& instanceExtensions, 303 const vector<string>& deviceExtensions) 304 { 305 deMemset(&coreFeatures, 0, sizeof(coreFeatures)); 306 deMemset(&samplerYCbCrConversionFeatures, 0, sizeof(samplerYCbCrConversionFeatures)); 307 308 coreFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; 309 samplerYCbCrConversionFeatures.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES; 310 311 if (isPhysicalDeviceFeatures2Supported(apiVersion, instanceExtensions)) 312 { 313 if (de::contains(deviceExtensions.begin(), deviceExtensions.end(), "VK_KHR_sampler_ycbcr_conversion")) 314 coreFeatures.pNext = &samplerYCbCrConversionFeatures; 315 316 vki.getPhysicalDeviceFeatures2(physicalDevice, &coreFeatures); 317 } 318 else 319 coreFeatures.features = getPhysicalDeviceFeatures(vki, physicalDevice); 320 321 // Disable robustness by default, as it has an impact on performance on some HW. 322 coreFeatures.features.robustBufferAccess = false; 323 } 324 }; 325 326 } // anonymous 327 328 class DefaultDevice 329 { 330 public: 331 DefaultDevice (const PlatformInterface& vkPlatform, const tcu::CommandLine& cmdLine); 332 ~DefaultDevice (void); 333 334 VkInstance getInstance (void) const { return *m_instance; } 335 const InstanceInterface& getInstanceInterface (void) const { return m_instanceInterface; } 336 deUint32 getAvailableInstanceVersion (void) const { return m_availableInstanceVersion; } 337 const vector<string>& getInstanceExtensions (void) const { return m_instanceExtensions; } 338 339 VkPhysicalDevice getPhysicalDevice (void) const { return m_physicalDevice; } 340 deUint32 getDeviceVersion (void) const { return m_deviceVersion; } 341 const VkPhysicalDeviceFeatures& getDeviceFeatures (void) const { return m_deviceFeatures.coreFeatures.features; } 342 const VkPhysicalDeviceFeatures2& getDeviceFeatures2 (void) const { return m_deviceFeatures.coreFeatures; } 343 const VkPhysicalDeviceSamplerYcbcrConversionFeatures& getSamplerYCbCrConversionFeatures (void) const { return m_deviceFeatures.samplerYCbCrConversionFeatures; } 344 VkDevice getDevice (void) const { return *m_device; } 345 const DeviceInterface& getDeviceInterface (void) const { return m_deviceInterface; } 346 const VkPhysicalDeviceProperties& getDeviceProperties (void) const { return m_deviceProperties; } 347 const vector<string>& getDeviceExtensions (void) const { return m_deviceExtensions; } 348 349 deUint32 getUsedApiVersion (void) const { return m_usedApiVersion; } 350 351 deUint32 getUniversalQueueFamilyIndex (void) const { return m_universalQueueFamilyIndex; } 352 VkQueue getUniversalQueue (void) const; 353 354 private: 355 356 const deUint32 m_availableInstanceVersion; 357 358 const std::pair<deUint32, deUint32> m_deviceVersions; 359 const deUint32 m_usedApiVersion; 360 361 const vector<string> m_instanceExtensions; 362 const Unique<VkInstance> m_instance; 363 const InstanceDriver m_instanceInterface; 364 365 const VkPhysicalDevice m_physicalDevice; 366 const deUint32 m_deviceVersion; 367 368 const deUint32 m_universalQueueFamilyIndex; 369 const VkPhysicalDeviceProperties m_deviceProperties; 370 371 const vector<string> m_deviceExtensions; 372 const DeviceFeatures m_deviceFeatures; 373 374 const Unique<VkDevice> m_device; 375 const DeviceDriver m_deviceInterface; 376 377 }; 378 379 DefaultDevice::DefaultDevice (const PlatformInterface& vkPlatform, const tcu::CommandLine& cmdLine) 380 : m_availableInstanceVersion (getTargetInstanceVersion(vkPlatform)) 381 , m_deviceVersions (determineDeviceVersions(vkPlatform, m_availableInstanceVersion, cmdLine)) 382 , m_usedApiVersion (deMinu32(m_availableInstanceVersion, m_deviceVersions.first)) 383 384 , m_instanceExtensions (addCoreInstanceExtensions(filterExtensions(enumerateInstanceExtensionProperties(vkPlatform, DE_NULL)), m_usedApiVersion)) 385 , m_instance (createInstance(vkPlatform, m_usedApiVersion, m_instanceExtensions, cmdLine)) 386 387 , m_instanceInterface (vkPlatform, *m_instance) 388 , m_physicalDevice (chooseDevice(m_instanceInterface, *m_instance, cmdLine)) 389 , m_deviceVersion (getPhysicalDeviceProperties(m_instanceInterface, m_physicalDevice).apiVersion) 390 391 , m_universalQueueFamilyIndex (findQueueFamilyIndexWithCaps(m_instanceInterface, m_physicalDevice, VK_QUEUE_GRAPHICS_BIT|VK_QUEUE_COMPUTE_BIT)) 392 , m_deviceProperties (getPhysicalDeviceProperties(m_instanceInterface, m_physicalDevice)) 393 , m_deviceExtensions (addCoreDeviceExtensions(filterExtensions(enumerateDeviceExtensionProperties(m_instanceInterface, m_physicalDevice, DE_NULL)), m_usedApiVersion)) 394 , m_deviceFeatures (m_instanceInterface, m_usedApiVersion, m_physicalDevice, m_instanceExtensions, m_deviceExtensions) 395 , m_device (createDefaultDevice(m_instanceInterface, m_physicalDevice, m_usedApiVersion, m_universalQueueFamilyIndex, m_deviceFeatures.coreFeatures, m_deviceExtensions, cmdLine)) 396 , m_deviceInterface (m_instanceInterface, *m_device) 397 { 398 DE_ASSERT(m_deviceVersions.first == m_deviceVersion); 399 } 400 401 DefaultDevice::~DefaultDevice (void) 402 { 403 } 404 405 VkQueue DefaultDevice::getUniversalQueue (void) const 406 { 407 return getDeviceQueue(m_deviceInterface, *m_device, m_universalQueueFamilyIndex, 0); 408 } 409 410 // Allocator utilities 411 412 vk::Allocator* createAllocator (DefaultDevice* device) 413 { 414 const VkPhysicalDeviceMemoryProperties memoryProperties = vk::getPhysicalDeviceMemoryProperties(device->getInstanceInterface(), device->getPhysicalDevice()); 415 416 // \todo [2015-07-24 jarkko] support allocator selection/configuration from command line (or compile time) 417 return new SimpleAllocator(device->getDeviceInterface(), device->getDevice(), memoryProperties); 418 } 419 420 // Context 421 422 Context::Context (tcu::TestContext& testCtx, 423 const vk::PlatformInterface& platformInterface, 424 vk::BinaryCollection& progCollection) 425 : m_testCtx (testCtx) 426 , m_platformInterface (platformInterface) 427 , m_progCollection (progCollection) 428 , m_device (new DefaultDevice(m_platformInterface, testCtx.getCommandLine())) 429 , m_allocator (createAllocator(m_device.get())) 430 { 431 } 432 433 Context::~Context (void) 434 { 435 } 436 437 deUint32 Context::getAvailableInstanceVersion (void) const { return m_device->getAvailableInstanceVersion(); } 438 const vector<string>& Context::getInstanceExtensions (void) const { return m_device->getInstanceExtensions(); } 439 vk::VkInstance Context::getInstance (void) const { return m_device->getInstance(); } 440 const vk::InstanceInterface& Context::getInstanceInterface (void) const { return m_device->getInstanceInterface(); } 441 vk::VkPhysicalDevice Context::getPhysicalDevice (void) const { return m_device->getPhysicalDevice(); } 442 deUint32 Context::getDeviceVersion (void) const { return m_device->getDeviceVersion(); } 443 const vk::VkPhysicalDeviceFeatures& Context::getDeviceFeatures (void) const { return m_device->getDeviceFeatures(); } 444 const vk::VkPhysicalDeviceFeatures2& Context::getDeviceFeatures2 (void) const { return m_device->getDeviceFeatures2(); } 445 const vk::VkPhysicalDeviceSamplerYcbcrConversionFeatures& 446 Context::getSamplerYCbCrConversionFeatures 447 (void) const { return m_device->getSamplerYCbCrConversionFeatures(); } 448 const vk::VkPhysicalDeviceProperties& Context::getDeviceProperties (void) const { return m_device->getDeviceProperties(); } 449 const vector<string>& Context::getDeviceExtensions (void) const { return m_device->getDeviceExtensions(); } 450 vk::VkDevice Context::getDevice (void) const { return m_device->getDevice(); } 451 const vk::DeviceInterface& Context::getDeviceInterface (void) const { return m_device->getDeviceInterface(); } 452 deUint32 Context::getUniversalQueueFamilyIndex (void) const { return m_device->getUniversalQueueFamilyIndex(); } 453 vk::VkQueue Context::getUniversalQueue (void) const { return m_device->getUniversalQueue(); } 454 vk::Allocator& Context::getDefaultAllocator (void) const { return *m_allocator; } 455 deUint32 Context::getUsedApiVersion (void) const { return m_device->getUsedApiVersion(); } 456 bool Context::contextSupports (const deUint32 majorNum, const deUint32 minorNum, const deUint32 patchNum) const 457 { return m_device->getUsedApiVersion() >= VK_MAKE_VERSION(majorNum, minorNum, patchNum); } 458 bool Context::contextSupports (const ApiVersion version) const 459 { return m_device->getUsedApiVersion() >= pack(version); } 460 bool Context::contextSupports (const deUint32 requiredApiVersionBits) const 461 { return m_device->getUsedApiVersion() >= requiredApiVersionBits; } 462 463 // TestCase 464 465 void TestCase::initPrograms (SourceCollections&) const 466 { 467 } 468 469 } // vkt 470