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 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 82 vector<string> getValidationLayers (const PlatformInterface& vkp) 83 { 84 return getValidationLayers(enumerateInstanceLayerProperties(vkp)); 85 } 86 87 vector<string> getValidationLayers (const InstanceInterface& vki, VkPhysicalDevice physicalDevice) 88 { 89 return getValidationLayers(enumerateDeviceLayerProperties(vki, physicalDevice)); 90 } 91 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 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 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 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 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 211 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 250 VkInstance getInstance (void) const { return *m_instance; } 251 const InstanceInterface& getInstanceInterface (void) const { return m_instanceInterface; } 252 const vector<string>& getInstanceExtensions (void) const { return m_instanceExtensions; } 253 254 VkPhysicalDevice getPhysicalDevice (void) const { return m_physicalDevice; } 255 const VkPhysicalDeviceFeatures& getDeviceFeatures (void) const { return m_deviceFeatures.coreFeatures.features; } 256 const VkPhysicalDeviceFeatures2KHR& getDeviceFeatures2 (void) const { return m_deviceFeatures.coreFeatures; } 257 VkDevice getDevice (void) const { return *m_device; } 258 const DeviceInterface& getDeviceInterface (void) const { return m_deviceInterface; } 259 const VkPhysicalDeviceProperties& getDeviceProperties (void) const { return m_deviceProperties; } 260 const vector<string>& getDeviceExtensions (void) const { return m_deviceExtensions; } 261 262 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 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 302 DefaultDevice::~DefaultDevice (void) 303 { 304 } 305 306 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 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 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 339 Context::~Context (void) 340 { 341 } 342 343 const vector<string>& Context::getInstanceExtensions (void) const { return m_device->getInstanceExtensions(); } 344 vk::VkInstance Context::getInstance (void) const { return m_device->getInstance(); } 345 const vk::InstanceInterface& Context::getInstanceInterface (void) const { return m_device->getInstanceInterface(); } 346 vk::VkPhysicalDevice Context::getPhysicalDevice (void) const { return m_device->getPhysicalDevice(); } 347 const vk::VkPhysicalDeviceFeatures& Context::getDeviceFeatures (void) const { return m_device->getDeviceFeatures(); } 348 const vk::VkPhysicalDeviceFeatures2KHR& Context::getDeviceFeatures2 (void) const { return m_device->getDeviceFeatures2(); } 349 const vk::VkPhysicalDeviceProperties& Context::getDeviceProperties (void) const { return m_device->getDeviceProperties(); } 350 const vector<string>& Context::getDeviceExtensions (void) const { return m_device->getDeviceExtensions(); } 351 vk::VkDevice Context::getDevice (void) const { return m_device->getDevice(); } 352 const vk::DeviceInterface& Context::getDeviceInterface (void) const { return m_device->getDeviceInterface(); } 353 deUint32 Context::getUniversalQueueFamilyIndex (void) const { return m_device->getUniversalQueueFamilyIndex(); } 354 vk::VkQueue Context::getUniversalQueue (void) const { return m_device->getUniversalQueue(); } 355 vk::Allocator& Context::getDefaultAllocator (void) const { return *m_allocator; } 356 357 // TestCase 358 359 void TestCase::initPrograms (SourceCollections&) const 360 { 361 } 362 363 } // vkt 364