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 "deMemory.h" 37 38 namespace vkt 39 { 40 41 // Default device utilities 42 43 using std::vector; 44 using std::string; 45 using namespace vk; 46 47 vector<string> getValidationLayers (const vector<VkLayerProperties>& supportedLayers) 48 { 49 static const char* s_magicLayer = "VK_LAYER_LUNARG_standard_validation"; 50 static const char* s_defaultLayers[] = 51 { 52 "VK_LAYER_GOOGLE_threading", 53 "VK_LAYER_LUNARG_parameter_validation", 54 "VK_LAYER_LUNARG_device_limits", 55 "VK_LAYER_LUNARG_object_tracker", 56 "VK_LAYER_LUNARG_image", 57 "VK_LAYER_LUNARG_core_validation", 58 "VK_LAYER_LUNARG_swapchain", 59 "VK_LAYER_GOOGLE_unique_objects" 60 }; 61 62 vector<string> enabledLayers; 63 64 if (isLayerSupported(supportedLayers, RequiredLayer(s_magicLayer))) 65 enabledLayers.push_back(s_magicLayer); 66 else 67 { 68 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_defaultLayers); ++ndx) 69 { 70 if (isLayerSupported(supportedLayers, RequiredLayer(s_defaultLayers[ndx]))) 71 enabledLayers.push_back(s_defaultLayers[ndx]); 72 } 73 } 74 75 return enabledLayers; 76 } 77 78 vector<string> getValidationLayers (const PlatformInterface& vkp) 79 { 80 return getValidationLayers(enumerateInstanceLayerProperties(vkp)); 81 } 82 83 vector<string> getValidationLayers (const InstanceInterface& vki, VkPhysicalDevice physicalDevice) 84 { 85 return getValidationLayers(enumerateDeviceLayerProperties(vki, physicalDevice)); 86 } 87 88 Move<VkInstance> createInstance (const PlatformInterface& vkp, const tcu::CommandLine& cmdLine) 89 { 90 const bool isValidationEnabled = cmdLine.isValidationEnabled(); 91 vector<string> enabledExtensions; 92 vector<string> enabledLayers; 93 94 if (isValidationEnabled) 95 { 96 if (isDebugReportSupported(vkp)) 97 enabledExtensions.push_back("VK_EXT_debug_report"); 98 else 99 TCU_THROW(NotSupportedError, "VK_EXT_debug_report is not supported"); 100 101 enabledLayers = getValidationLayers(vkp); 102 if (enabledLayers.empty()) 103 TCU_THROW(NotSupportedError, "No validation layers found"); 104 } 105 106 return createDefaultInstance(vkp, enabledLayers, enabledExtensions); 107 } 108 109 static deUint32 findQueueFamilyIndexWithCaps (const InstanceInterface& vkInstance, VkPhysicalDevice physicalDevice, VkQueueFlags requiredCaps) 110 { 111 const vector<VkQueueFamilyProperties> queueProps = getPhysicalDeviceQueueFamilyProperties(vkInstance, physicalDevice); 112 113 for (size_t queueNdx = 0; queueNdx < queueProps.size(); queueNdx++) 114 { 115 if ((queueProps[queueNdx].queueFlags & requiredCaps) == requiredCaps) 116 return (deUint32)queueNdx; 117 } 118 119 TCU_THROW(NotSupportedError, "No matching queue found"); 120 } 121 122 Move<VkDevice> createDefaultDevice (const InstanceInterface& vki, 123 VkPhysicalDevice physicalDevice, 124 deUint32 queueIndex, 125 const VkPhysicalDeviceFeatures& enabledFeatures, 126 const vector<string>& enabledExtensions, 127 const tcu::CommandLine& cmdLine) 128 { 129 VkDeviceQueueCreateInfo queueInfo; 130 VkDeviceCreateInfo deviceInfo; 131 vector<string> enabledLayers; 132 vector<const char*> layerPtrs; 133 vector<const char*> extensionPtrs; 134 const float queuePriority = 1.0f; 135 136 deMemset(&queueInfo, 0, sizeof(queueInfo)); 137 deMemset(&deviceInfo, 0, sizeof(deviceInfo)); 138 139 if (cmdLine.isValidationEnabled()) 140 { 141 enabledLayers = getValidationLayers(vki, physicalDevice); 142 if (enabledLayers.empty()) 143 TCU_THROW(NotSupportedError, "No validation layers found"); 144 } 145 146 layerPtrs.resize(enabledLayers.size()); 147 148 for (size_t ndx = 0; ndx < enabledLayers.size(); ++ndx) 149 layerPtrs[ndx] = enabledLayers[ndx].c_str(); 150 151 extensionPtrs.resize(enabledExtensions.size()); 152 153 for (size_t ndx = 0; ndx < enabledExtensions.size(); ++ndx) 154 extensionPtrs[ndx] = enabledExtensions[ndx].c_str(); 155 156 queueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; 157 queueInfo.pNext = DE_NULL; 158 queueInfo.flags = (VkDeviceQueueCreateFlags)0u; 159 queueInfo.queueFamilyIndex = queueIndex; 160 queueInfo.queueCount = 1u; 161 queueInfo.pQueuePriorities = &queuePriority; 162 163 deviceInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; 164 deviceInfo.pNext = DE_NULL; 165 deviceInfo.queueCreateInfoCount = 1u; 166 deviceInfo.pQueueCreateInfos = &queueInfo; 167 deviceInfo.enabledExtensionCount = (deUint32)extensionPtrs.size(); 168 deviceInfo.ppEnabledExtensionNames = (extensionPtrs.empty() ? DE_NULL : &extensionPtrs[0]); 169 deviceInfo.enabledLayerCount = (deUint32)layerPtrs.size(); 170 deviceInfo.ppEnabledLayerNames = (layerPtrs.empty() ? DE_NULL : &layerPtrs[0]); 171 deviceInfo.pEnabledFeatures = &enabledFeatures; 172 173 return createDevice(vki, physicalDevice, &deviceInfo); 174 }; 175 176 class DefaultDevice 177 { 178 public: 179 DefaultDevice (const PlatformInterface& vkPlatform, const tcu::CommandLine& cmdLine); 180 ~DefaultDevice (void); 181 182 VkInstance getInstance (void) const { return *m_instance; } 183 const InstanceInterface& getInstanceInterface (void) const { return m_instanceInterface; } 184 185 VkPhysicalDevice getPhysicalDevice (void) const { return m_physicalDevice; } 186 const VkPhysicalDeviceFeatures& getDeviceFeatures (void) const { return m_deviceFeatures; } 187 VkDevice getDevice (void) const { return *m_device; } 188 const DeviceInterface& getDeviceInterface (void) const { return m_deviceInterface; } 189 const VkPhysicalDeviceProperties& getDeviceProperties (void) const { return m_deviceProperties; } 190 const vector<string>& getDeviceExtensions (void) const { return m_deviceExtensions; } 191 192 deUint32 getUniversalQueueFamilyIndex (void) const { return m_universalQueueFamilyIndex; } 193 VkQueue getUniversalQueue (void) const; 194 195 private: 196 static VkPhysicalDeviceFeatures filterDefaultDeviceFeatures (const VkPhysicalDeviceFeatures& deviceFeatures); 197 static vector<string> filterDefaultDeviceExtensions (const vector<VkExtensionProperties>& deviceExtensions); 198 199 const Unique<VkInstance> m_instance; 200 const InstanceDriver m_instanceInterface; 201 202 const VkPhysicalDevice m_physicalDevice; 203 204 const deUint32 m_universalQueueFamilyIndex; 205 const VkPhysicalDeviceFeatures m_deviceFeatures; 206 const VkPhysicalDeviceProperties m_deviceProperties; 207 const vector<string> m_deviceExtensions; 208 209 const Unique<VkDevice> m_device; 210 const DeviceDriver m_deviceInterface; 211 }; 212 213 DefaultDevice::DefaultDevice (const PlatformInterface& vkPlatform, const tcu::CommandLine& cmdLine) 214 : m_instance (createInstance(vkPlatform, cmdLine)) 215 , m_instanceInterface (vkPlatform, *m_instance) 216 , m_physicalDevice (chooseDevice(m_instanceInterface, *m_instance, cmdLine)) 217 , m_universalQueueFamilyIndex (findQueueFamilyIndexWithCaps(m_instanceInterface, m_physicalDevice, VK_QUEUE_GRAPHICS_BIT|VK_QUEUE_COMPUTE_BIT)) 218 , m_deviceFeatures (filterDefaultDeviceFeatures(getPhysicalDeviceFeatures(m_instanceInterface, m_physicalDevice))) 219 , m_deviceProperties (getPhysicalDeviceProperties(m_instanceInterface, m_physicalDevice)) 220 , m_deviceExtensions (filterDefaultDeviceExtensions(enumerateDeviceExtensionProperties(m_instanceInterface, m_physicalDevice, DE_NULL))) 221 , m_device (createDefaultDevice(m_instanceInterface, m_physicalDevice, m_universalQueueFamilyIndex, m_deviceFeatures, m_deviceExtensions, cmdLine)) 222 , m_deviceInterface (m_instanceInterface, *m_device) 223 { 224 } 225 226 DefaultDevice::~DefaultDevice (void) 227 { 228 } 229 230 VkQueue DefaultDevice::getUniversalQueue (void) const 231 { 232 VkQueue queue = 0; 233 m_deviceInterface.getDeviceQueue(*m_device, m_universalQueueFamilyIndex, 0, &queue); 234 return queue; 235 } 236 237 VkPhysicalDeviceFeatures DefaultDevice::filterDefaultDeviceFeatures (const VkPhysicalDeviceFeatures& deviceFeatures) 238 { 239 VkPhysicalDeviceFeatures enabledDeviceFeatures = deviceFeatures; 240 241 // Disable robustness by default, as it has an impact on performance on some HW. 242 enabledDeviceFeatures.robustBufferAccess = false; 243 244 return enabledDeviceFeatures; 245 } 246 247 vector<string> DefaultDevice::filterDefaultDeviceExtensions (const vector<VkExtensionProperties>& deviceExtensions) 248 { 249 vector<string> enabledExtensions; 250 251 // The only extension we enable always (when supported) is 252 // VK_KHR_sampler_mirror_clamp_to_edge that is defined in 253 // the core spec and supported widely. 254 const char* const mirrorClampToEdgeExt = "VK_KHR_sampler_mirror_clamp_to_edge"; 255 if (vk::isExtensionSupported(deviceExtensions, vk::RequiredExtension(mirrorClampToEdgeExt))) 256 enabledExtensions.push_back(mirrorClampToEdgeExt); 257 258 return enabledExtensions; 259 } 260 261 // Allocator utilities 262 263 vk::Allocator* createAllocator (DefaultDevice* device) 264 { 265 const VkPhysicalDeviceMemoryProperties memoryProperties = vk::getPhysicalDeviceMemoryProperties(device->getInstanceInterface(), device->getPhysicalDevice()); 266 267 // \todo [2015-07-24 jarkko] support allocator selection/configuration from command line (or compile time) 268 return new SimpleAllocator(device->getDeviceInterface(), device->getDevice(), memoryProperties); 269 } 270 271 // Context 272 273 Context::Context (tcu::TestContext& testCtx, 274 const vk::PlatformInterface& platformInterface, 275 vk::ProgramCollection<vk::ProgramBinary>& progCollection) 276 : m_testCtx (testCtx) 277 , m_platformInterface (platformInterface) 278 , m_progCollection (progCollection) 279 , m_device (new DefaultDevice(m_platformInterface, testCtx.getCommandLine())) 280 , m_allocator (createAllocator(m_device.get())) 281 { 282 } 283 284 Context::~Context (void) 285 { 286 } 287 288 vk::VkInstance Context::getInstance (void) const { return m_device->getInstance(); } 289 const vk::InstanceInterface& Context::getInstanceInterface (void) const { return m_device->getInstanceInterface(); } 290 vk::VkPhysicalDevice Context::getPhysicalDevice (void) const { return m_device->getPhysicalDevice(); } 291 const vk::VkPhysicalDeviceFeatures& Context::getDeviceFeatures (void) const { return m_device->getDeviceFeatures(); } 292 const vk::VkPhysicalDeviceProperties& Context::getDeviceProperties (void) const { return m_device->getDeviceProperties(); } 293 const vector<string>& Context::getDeviceExtensions (void) const { return m_device->getDeviceExtensions(); } 294 vk::VkDevice Context::getDevice (void) const { return m_device->getDevice(); } 295 const vk::DeviceInterface& Context::getDeviceInterface (void) const { return m_device->getDeviceInterface(); } 296 deUint32 Context::getUniversalQueueFamilyIndex (void) const { return m_device->getUniversalQueueFamilyIndex(); } 297 vk::VkQueue Context::getUniversalQueue (void) const { return m_device->getUniversalQueue(); } 298 vk::Allocator& Context::getDefaultAllocator (void) const { return *m_allocator; } 299 300 // TestCase 301 302 void TestCase::initPrograms (SourceCollections&) const 303 { 304 } 305 306 } // vkt 307