1 /*------------------------------------------------------------------------- 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2017 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 Utilities for Vulkan SPIR-V assembly tests 22 *//*--------------------------------------------------------------------*/ 23 24 #include "vktSpvAsmUtils.hpp" 25 26 #include "deMemory.h" 27 #include "deSTLUtil.hpp" 28 #include "vkQueryUtil.hpp" 29 #include "vkRefUtil.hpp" 30 31 namespace vkt 32 { 33 namespace SpirVAssembly 34 { 35 36 using namespace vk; 37 38 namespace 39 { 40 41 VkPhysicalDeviceFeatures filterDefaultDeviceFeatures (const VkPhysicalDeviceFeatures& deviceFeatures) 42 { 43 VkPhysicalDeviceFeatures enabledDeviceFeatures = deviceFeatures; 44 45 // Disable robustness by default, as it has an impact on performance on some HW. 46 enabledDeviceFeatures.robustBufferAccess = false; 47 48 return enabledDeviceFeatures; 49 } 50 51 VkPhysicalDevice16BitStorageFeatures querySupported16BitStorageFeatures (const deUint32 apiVersion, const InstanceInterface& vki, VkPhysicalDevice device, const std::vector<std::string>& instanceExtensions) 52 { 53 VkPhysicalDevice16BitStorageFeatures extensionFeatures = 54 { 55 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_16BIT_STORAGE_FEATURES_KHR, // sType 56 DE_NULL, // pNext 57 false, // storageUniformBufferBlock16 58 false, // storageUniform16 59 false, // storagePushConstant16 60 false, // storageInputOutput16 61 }; 62 VkPhysicalDeviceFeatures2 features; 63 64 deMemset(&features, 0, sizeof(features)); 65 features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; 66 features.pNext = &extensionFeatures; 67 68 // Call the getter only if supported. Otherwise above "zero" defaults are used 69 if(isInstanceExtensionSupported(apiVersion, instanceExtensions, "VK_KHR_get_physical_device_properties2")) 70 { 71 vki.getPhysicalDeviceFeatures2(device, &features); 72 } 73 74 return extensionFeatures; 75 } 76 77 VkPhysicalDeviceVariablePointerFeatures querySupportedVariablePointersFeatures (const deUint32 apiVersion, const InstanceInterface& vki, VkPhysicalDevice device, const std::vector<std::string>& instanceExtensions) 78 { 79 VkPhysicalDeviceVariablePointerFeatures extensionFeatures = 80 { 81 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VARIABLE_POINTER_FEATURES_KHR, // sType 82 DE_NULL, // pNext 83 false, // variablePointersStorageBuffer 84 false, // variablePointers 85 }; 86 87 VkPhysicalDeviceFeatures2 features; 88 deMemset(&features, 0, sizeof(features)); 89 features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2; 90 features.pNext = &extensionFeatures; 91 92 // Call the getter only if supported. Otherwise above "zero" defaults are used 93 if(isInstanceExtensionSupported(apiVersion, instanceExtensions, "VK_KHR_get_physical_device_properties2")) 94 { 95 vki.getPhysicalDeviceFeatures2(device, &features); 96 } 97 98 return extensionFeatures; 99 } 100 101 } // anonymous 102 103 bool is16BitStorageFeaturesSupported (const deUint32 apiVersion, const InstanceInterface& vki, VkPhysicalDevice device, const std::vector<std::string>& instanceExtensions, Extension16BitStorageFeatures toCheck) 104 { 105 VkPhysicalDevice16BitStorageFeatures extensionFeatures = querySupported16BitStorageFeatures(apiVersion, vki, device, instanceExtensions); 106 107 if ((toCheck & EXT16BITSTORAGEFEATURES_UNIFORM_BUFFER_BLOCK) != 0 && extensionFeatures.storageBuffer16BitAccess == VK_FALSE) 108 return false; 109 110 if ((toCheck & EXT16BITSTORAGEFEATURES_UNIFORM) != 0 && extensionFeatures.uniformAndStorageBuffer16BitAccess == VK_FALSE) 111 return false; 112 113 if ((toCheck & EXT16BITSTORAGEFEATURES_PUSH_CONSTANT) != 0 && extensionFeatures.storagePushConstant16 == VK_FALSE) 114 return false; 115 116 if ((toCheck & EXT16BITSTORAGEFEATURES_INPUT_OUTPUT) != 0 && extensionFeatures.storageInputOutput16 == VK_FALSE) 117 return false; 118 119 return true; 120 } 121 122 bool isVariablePointersFeaturesSupported (const deUint32 apiVersion, const InstanceInterface& vki, VkPhysicalDevice device, const std::vector<std::string>& instanceExtensions, ExtensionVariablePointersFeatures toCheck) 123 { 124 VkPhysicalDeviceVariablePointerFeatures extensionFeatures = querySupportedVariablePointersFeatures(apiVersion, vki, device, instanceExtensions); 125 126 if ((toCheck & EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS_STORAGEBUFFER) != 0 && extensionFeatures.variablePointersStorageBuffer == VK_FALSE) 127 return false; 128 129 if ((toCheck & EXTVARIABLEPOINTERSFEATURES_VARIABLE_POINTERS) != 0 && extensionFeatures.variablePointers == VK_FALSE) 130 return false; 131 132 return true; 133 } 134 135 Move<VkDevice> createDeviceWithExtensions (Context& context, 136 const deUint32 queueFamilyIndex, 137 const std::vector<std::string>& supportedExtensions, 138 const std::vector<std::string>& requiredExtensions) 139 { 140 const InstanceInterface& vki = context.getInstanceInterface(); 141 const VkPhysicalDevice physicalDevice = context.getPhysicalDevice(); 142 std::vector<const char*> extensions; 143 void* pExtension = DE_NULL; 144 const VkPhysicalDeviceFeatures deviceFeatures = getPhysicalDeviceFeatures(vki, physicalDevice); 145 VkPhysicalDevice16BitStorageFeatures ext16BitStorageFeatures; 146 VkPhysicalDeviceVariablePointerFeatures extVariablePointerFeatures; 147 148 for (deUint32 extNdx = 0; extNdx < requiredExtensions.size(); ++extNdx) 149 { 150 const std::string& ext = requiredExtensions[extNdx]; 151 152 // Check that all required extensions are supported first. 153 if (!isDeviceExtensionSupported(context.getUsedApiVersion(), supportedExtensions, ext)) 154 { 155 TCU_THROW(NotSupportedError, (std::string("Device extension not supported: ") + ext).c_str()); 156 } 157 158 // Currently don't support enabling multiple extensions at the same time. 159 if (ext == "VK_KHR_16bit_storage") 160 { 161 // For the 16bit storage extension, we have four features to test. Requesting all features supported. 162 // Note that we don't throw NotImplemented errors here if a specific feature is not supported; 163 // that should be done when actually trying to use that specific feature. 164 ext16BitStorageFeatures = querySupported16BitStorageFeatures(context.getUsedApiVersion(), vki, physicalDevice, context.getInstanceExtensions()); 165 pExtension = &ext16BitStorageFeatures; 166 } 167 else if (ext == "VK_KHR_variable_pointers") 168 { 169 // For the VariablePointers extension, we have two features to test. Requesting all features supported. 170 extVariablePointerFeatures = querySupportedVariablePointersFeatures(context.getUsedApiVersion(), vki, physicalDevice, context.getInstanceExtensions()); 171 pExtension = &extVariablePointerFeatures; 172 } 173 174 if (!isCoreDeviceExtension(context.getUsedApiVersion(), ext)) 175 extensions.push_back(ext.c_str()); 176 } 177 178 const float queuePriorities[] = { 1.0f }; 179 const VkDeviceQueueCreateInfo queueInfos[] = 180 { 181 { 182 VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO, 183 DE_NULL, 184 (VkDeviceQueueCreateFlags)0, 185 queueFamilyIndex, 186 DE_LENGTH_OF_ARRAY(queuePriorities), 187 &queuePriorities[0] 188 } 189 }; 190 const VkPhysicalDeviceFeatures features = filterDefaultDeviceFeatures(deviceFeatures); 191 const VkDeviceCreateInfo deviceParams = 192 { 193 VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, 194 pExtension, 195 (VkDeviceCreateFlags)0, 196 DE_LENGTH_OF_ARRAY(queueInfos), 197 &queueInfos[0], 198 0u, 199 DE_NULL, 200 (deUint32)extensions.size(), 201 extensions.empty() ? DE_NULL : &extensions[0], 202 &features 203 }; 204 205 return vk::createDevice(vki, physicalDevice, &deviceParams); 206 } 207 208 Allocator* createAllocator (const InstanceInterface& instanceInterface, const VkPhysicalDevice physicalDevice, const DeviceInterface& deviceInterface, const VkDevice device) 209 { 210 const VkPhysicalDeviceMemoryProperties memoryProperties = getPhysicalDeviceMemoryProperties(instanceInterface, physicalDevice); 211 212 // \todo [2015-07-24 jarkko] support allocator selection/configuration from command line (or compile time) 213 return new SimpleAllocator(deviceInterface, device, memoryProperties); 214 } 215 216 deUint32 getMinRequiredVulkanVersion (const SpirvVersion version) 217 { 218 switch(version) 219 { 220 case SPIRV_VERSION_1_0: 221 return VK_API_VERSION_1_0; 222 case SPIRV_VERSION_1_1: 223 case SPIRV_VERSION_1_2: 224 case SPIRV_VERSION_1_3: 225 return VK_API_VERSION_1_1; 226 default: 227 DE_ASSERT(0); 228 } 229 return 0u; 230 } 231 232 std::string getVulkanName (const deUint32 version) 233 { 234 return std::string(version == VK_API_VERSION_1_1 ? "1.1" : "1.0"); 235 } 236 237 } // SpirVAssembly 238 } // vkt 239