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 39namespace vkt 40{ 41 42// Default device utilities 43 44using std::vector; 45using std::string; 46using namespace vk; 47 48namespace 49{ 50 51vector<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 82vector<string> getValidationLayers (const PlatformInterface& vkp) 83{ 84 return getValidationLayers(enumerateInstanceLayerProperties(vkp)); 85} 86 87vector<string> getValidationLayers (const InstanceInterface& vki, VkPhysicalDevice physicalDevice) 88{ 89 return getValidationLayers(enumerateDeviceLayerProperties(vki, physicalDevice)); 90} 91 92vector<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 114Move<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 132static 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 145Move<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 201bool isPhysicalDeviceFeatures2Supported (const vector<string>& instanceExtensions) 202{ 203 return de::contains(instanceExtensions.begin(), instanceExtensions.end(), "VK_KHR_get_physical_device_properties2"); 204} 205 206struct 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 244class DefaultDevice 245{ 246public: 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 265private: 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 283DefaultDevice::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 302DefaultDevice::~DefaultDevice (void) 303{ 304} 305 306VkQueue DefaultDevice::getUniversalQueue (void) const 307{ 308 return getDeviceQueue(m_deviceInterface, *m_device, m_universalQueueFamilyIndex, 0); 309} 310 311namespace 312{ 313 314// Allocator utilities 315 316vk::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 328Context::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 339Context::~Context (void) 340{ 341} 342 343const vector<string>& Context::getInstanceExtensions (void) const { return m_device->getInstanceExtensions(); } 344vk::VkInstance Context::getInstance (void) const { return m_device->getInstance(); } 345const vk::InstanceInterface& Context::getInstanceInterface (void) const { return m_device->getInstanceInterface(); } 346vk::VkPhysicalDevice Context::getPhysicalDevice (void) const { return m_device->getPhysicalDevice(); } 347const vk::VkPhysicalDeviceFeatures& Context::getDeviceFeatures (void) const { return m_device->getDeviceFeatures(); } 348const vk::VkPhysicalDeviceFeatures2KHR& Context::getDeviceFeatures2 (void) const { return m_device->getDeviceFeatures2(); } 349const vk::VkPhysicalDeviceProperties& Context::getDeviceProperties (void) const { return m_device->getDeviceProperties(); } 350const vector<string>& Context::getDeviceExtensions (void) const { return m_device->getDeviceExtensions(); } 351vk::VkDevice Context::getDevice (void) const { return m_device->getDevice(); } 352const vk::DeviceInterface& Context::getDeviceInterface (void) const { return m_device->getDeviceInterface(); } 353deUint32 Context::getUniversalQueueFamilyIndex (void) const { return m_device->getUniversalQueueFamilyIndex(); } 354vk::VkQueue Context::getUniversalQueue (void) const { return m_device->getUniversalQueue(); } 355vk::Allocator& Context::getDefaultAllocator (void) const { return *m_allocator; } 356 357// TestCase 358 359void TestCase::initPrograms (SourceCollections&) const 360{ 361} 362 363} // vkt 364