1 /*------------------------------------------------------------------------- 2 * Vulkan CTS 3 * ---------- 4 * 5 * Copyright (c) 2019 The Khronos Group 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 #include "deSTLUtil.hpp" 21 #include "deString.h" 22 #include "vkQueryUtil.hpp" 23 #include "vkDeviceFeatures.inl" 24 #include "vkDeviceFeatures.hpp" 25 26 namespace vk 27 { 28 DeviceFeatures(const InstanceInterface & vki,const deUint32 apiVersion,const VkPhysicalDevice physicalDevice,const std::vector<std::string> & instanceExtensions,const std::vector<std::string> & deviceExtensions,const deBool enableAllFeatures)29 DeviceFeatures::DeviceFeatures(const InstanceInterface &vki, 30 const deUint32 apiVersion, 31 const VkPhysicalDevice physicalDevice, 32 const std::vector<std::string> &instanceExtensions, 33 const std::vector<std::string> &deviceExtensions, 34 const deBool enableAllFeatures) 35 { 36 VkPhysicalDeviceRobustness2FeaturesEXT *robustness2Features = nullptr; 37 VkPhysicalDeviceImageRobustnessFeaturesEXT *imageRobustnessFeatures = nullptr; 38 #ifndef CTS_USES_VULKANSC 39 VkPhysicalDeviceFragmentShadingRateFeaturesKHR *fragmentShadingRateFeatures = nullptr; 40 VkPhysicalDeviceShadingRateImageFeaturesNV *shadingRateImageFeaturesNV = nullptr; 41 VkPhysicalDeviceFragmentDensityMapFeaturesEXT *fragmentDensityMapFeatures = nullptr; 42 VkPhysicalDevicePageableDeviceLocalMemoryFeaturesEXT *pageableDeviceLocalMemoryFeatures = nullptr; 43 VkPhysicalDeviceMutableDescriptorTypeFeaturesEXT *mutableDescriptorTypeFeatures = nullptr; 44 #endif // CTS_USES_VULKANSC 45 46 m_coreFeatures2 = initVulkanStructure(); 47 m_vulkan11Features = initVulkanStructure(); 48 m_vulkan12Features = initVulkanStructure(); 49 #ifndef CTS_USES_VULKANSC 50 m_vulkan13Features = initVulkanStructure(); 51 #endif // CTS_USES_VULKANSC 52 #ifdef CTS_USES_VULKANSC 53 m_vulkanSC10Features = initVulkanStructure(); 54 #endif // CTS_USES_VULKANSC 55 56 if (isInstanceExtensionSupported(apiVersion, instanceExtensions, "VK_KHR_get_physical_device_properties2")) 57 { 58 const std::vector<VkExtensionProperties> deviceExtensionProperties = enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL); 59 void **nextPtr = &m_coreFeatures2.pNext; 60 std::vector<FeatureStructWrapperBase *> featuresToFillFromBlob; 61 #ifndef CTS_USES_VULKANSC 62 bool vk13Supported = (apiVersion >= VK_MAKE_API_VERSION(0, 1, 3, 0)); 63 #endif // CTS_USES_VULKANSC 64 bool vk12Supported = (apiVersion >= VK_MAKE_API_VERSION(0, 1, 2, 0)); 65 #ifdef CTS_USES_VULKANSC 66 bool vksc10Supported = (apiVersion >= VK_MAKE_API_VERSION(1, 1, 0, 0)); 67 #endif // CTS_USES_VULKANSC 68 69 // since vk12 we have blob structures combining features of couple previously 70 // available feature structures, that now in vk12+ must be removed from chain 71 if (vk12Supported) 72 { 73 addToChainVulkanStructure(&nextPtr, m_vulkan11Features); 74 addToChainVulkanStructure(&nextPtr, m_vulkan12Features); 75 76 #ifndef CTS_USES_VULKANSC 77 if (vk13Supported) 78 addToChainVulkanStructure(&nextPtr, m_vulkan13Features); 79 #endif // CTS_USES_VULKANSC 80 } 81 #ifdef CTS_USES_VULKANSC 82 if (vksc10Supported) 83 { 84 addToChainVulkanStructure(&nextPtr, m_vulkanSC10Features); 85 } 86 #endif // CTS_USES_VULKANSC 87 88 std::vector<std::string> allDeviceExtensions = deviceExtensions; 89 #ifdef CTS_USES_VULKANSC 90 // VulkanSC: add missing core extensions to the list 91 std::vector<const char *> coreExtensions; 92 getCoreDeviceExtensions(apiVersion, coreExtensions); 93 for (const auto &coreExt : coreExtensions) 94 if (!de::contains(allDeviceExtensions.begin(), allDeviceExtensions.end(), std::string(coreExt))) 95 allDeviceExtensions.push_back(coreExt); 96 #endif // CTS_USES_VULKANSC 97 98 // iterate over data for all feature that are defined in specification 99 for (const auto &featureStructCreationData : featureStructCreationArray) 100 { 101 const char *featureName = featureStructCreationData.name; 102 103 // check if this feature is available on current device 104 if ((de::contains(allDeviceExtensions.begin(), allDeviceExtensions.end(), featureName) || 105 std::string(featureName) == "core_feature") && 106 verifyFeatureAddCriteria(featureStructCreationData, deviceExtensionProperties)) 107 { 108 FeatureStructWrapperBase *p = (*featureStructCreationData.creatorFunction)(); 109 if (p == DE_NULL) 110 continue; 111 112 #ifdef CTS_USES_VULKANSC 113 // m_vulkanSC10Features was already added above 114 if (p->getFeatureDesc().sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_SC_1_0_FEATURES) 115 continue; 116 #endif // CTS_USES_VULKANSC 117 118 // if feature struct is part of VkPhysicalDeviceVulkan1{1,2,3}Features 119 // we dont add it to the chain but store and fill later from blob data 120 bool featureFilledFromBlob = false; 121 if (vk12Supported) 122 { 123 deUint32 blobApiVersion = getBlobFeaturesVersion(p->getFeatureDesc().sType); 124 if (blobApiVersion) 125 featureFilledFromBlob = (apiVersion >= blobApiVersion); 126 } 127 128 if (featureFilledFromBlob) 129 featuresToFillFromBlob.push_back(p); 130 else 131 { 132 VkStructureType structType = p->getFeatureDesc().sType; 133 void *rawStructPtr = p->getFeatureTypeRaw(); 134 135 if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT) 136 robustness2Features = reinterpret_cast<VkPhysicalDeviceRobustness2FeaturesEXT *>(rawStructPtr); 137 else if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES_EXT) 138 imageRobustnessFeatures = reinterpret_cast<VkPhysicalDeviceImageRobustnessFeaturesEXT *>(rawStructPtr); 139 #ifndef CTS_USES_VULKANSC 140 else if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR) 141 fragmentShadingRateFeatures = reinterpret_cast<VkPhysicalDeviceFragmentShadingRateFeaturesKHR *>(rawStructPtr); 142 else if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV) 143 shadingRateImageFeaturesNV = reinterpret_cast<VkPhysicalDeviceShadingRateImageFeaturesNV *>(rawStructPtr); 144 else if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT) 145 fragmentDensityMapFeatures = reinterpret_cast<VkPhysicalDeviceFragmentDensityMapFeaturesEXT *>(rawStructPtr); 146 else if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PAGEABLE_DEVICE_LOCAL_MEMORY_FEATURES_EXT) 147 pageableDeviceLocalMemoryFeatures = reinterpret_cast<VkPhysicalDevicePageableDeviceLocalMemoryFeaturesEXT *>(rawStructPtr); 148 else if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT) 149 mutableDescriptorTypeFeatures = reinterpret_cast<VkPhysicalDeviceMutableDescriptorTypeFeaturesEXT *>(rawStructPtr); 150 #endif // CTS_USES_VULKANSC 151 // add to chain 152 *nextPtr = rawStructPtr; 153 nextPtr = p->getFeatureTypeNext(); 154 } 155 m_features.push_back(p); 156 } 157 else 158 { 159 #ifndef CTS_USES_VULKANSC 160 // Some non-standard promotions may need feature structs filled in anyway. 161 if (!strcmp(featureName, "VK_EXT_extended_dynamic_state") && vk13Supported) 162 { 163 FeatureStructWrapperBase *p = (*featureStructCreationData.creatorFunction)(); 164 if (p == DE_NULL) 165 continue; 166 167 auto f = reinterpret_cast<VkPhysicalDeviceExtendedDynamicStateFeaturesEXT *>(p->getFeatureTypeRaw()); 168 f->extendedDynamicState = true; 169 m_features.push_back(p); 170 } 171 if (!strcmp(featureName, "VK_EXT_extended_dynamic_state2") && vk13Supported) 172 { 173 FeatureStructWrapperBase *p = (*featureStructCreationData.creatorFunction)(); 174 if (p == DE_NULL) 175 continue; 176 177 auto f = reinterpret_cast<VkPhysicalDeviceExtendedDynamicState2FeaturesEXT *>(p->getFeatureTypeRaw()); 178 f->extendedDynamicState2 = true; 179 m_features.push_back(p); 180 } 181 #endif // CTS_USES_VULKANSC 182 } 183 } 184 185 vki.getPhysicalDeviceFeatures2(physicalDevice, &m_coreFeatures2); 186 187 // fill data from VkPhysicalDeviceVulkan1{1,2,3}Features 188 if (vk12Supported) 189 { 190 AllFeaturesBlobs allBlobs = 191 { 192 m_vulkan11Features, 193 m_vulkan12Features, 194 #ifndef CTS_USES_VULKANSC 195 m_vulkan13Features, 196 #endif // CTS_USES_VULKANSC 197 // add blobs from future vulkan versions here 198 }; 199 200 for (auto feature : featuresToFillFromBlob) 201 feature->initializeFeatureFromBlob(allBlobs); 202 } 203 } 204 else 205 m_coreFeatures2.features = getPhysicalDeviceFeatures(vki, physicalDevice); 206 207 // 'enableAllFeatures' is used to create a complete list of supported features. 208 if (!enableAllFeatures) 209 { 210 // Disable robustness by default, as it has an impact on performance on some HW. 211 if (robustness2Features) 212 { 213 robustness2Features->robustBufferAccess2 = false; 214 robustness2Features->robustImageAccess2 = false; 215 robustness2Features->nullDescriptor = false; 216 } 217 if (imageRobustnessFeatures) 218 { 219 imageRobustnessFeatures->robustImageAccess = false; 220 } 221 m_coreFeatures2.features.robustBufferAccess = false; 222 223 #ifndef CTS_USES_VULKANSC 224 m_vulkan13Features.robustImageAccess = false; 225 226 // Disable VK_EXT_fragment_density_map and VK_NV_shading_rate_image features 227 // that must: not be enabled if KHR fragment shading rate features are enabled. 228 if (fragmentShadingRateFeatures && 229 (fragmentShadingRateFeatures->pipelineFragmentShadingRate || 230 fragmentShadingRateFeatures->primitiveFragmentShadingRate || 231 fragmentShadingRateFeatures->attachmentFragmentShadingRate)) 232 { 233 if (shadingRateImageFeaturesNV) 234 shadingRateImageFeaturesNV->shadingRateImage = false; 235 if (fragmentDensityMapFeatures) 236 fragmentDensityMapFeatures->fragmentDensityMap = false; 237 } 238 239 // Disable pageableDeviceLocalMemory by default since it may modify the behavior 240 // of device-local, and even host-local, memory allocations for all tests. 241 // pageableDeviceLocalMemory will use targetted testing on a custom device. 242 if (pageableDeviceLocalMemoryFeatures) 243 pageableDeviceLocalMemoryFeatures->pageableDeviceLocalMemory = false; 244 245 // Disable mutableDescriptorTypeFeatures by default because it can 246 // impact performance on some hardware. 247 if (mutableDescriptorTypeFeatures) 248 mutableDescriptorTypeFeatures->mutableDescriptorType = false; 249 #endif // CTS_USES_VULKANSC 250 } 251 } 252 verifyFeatureAddCriteria(const FeatureStructCreationData & item,const std::vector<VkExtensionProperties> & properties)253 bool DeviceFeatures::verifyFeatureAddCriteria(const FeatureStructCreationData &item, const std::vector<VkExtensionProperties> &properties) 254 { 255 #ifndef CTS_USES_VULKANSC 256 if (deStringEqual(item.name, VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME)) 257 { 258 for (const auto &property : properties) 259 { 260 if (deStringEqual(property.extensionName, item.name)) 261 return (property.specVersion == item.specVersion); 262 } 263 } 264 #else // CTS_USES_VULKANSC 265 DE_UNREF(item); 266 DE_UNREF(properties); 267 #endif // CTS_USES_VULKANSC 268 269 return true; 270 } 271 contains(const std::string & feature,bool throwIfNotExists) const272 bool DeviceFeatures::contains(const std::string &feature, bool throwIfNotExists) const 273 { 274 for (const auto f : m_features) 275 { 276 if (deStringEqual(f->getFeatureDesc().name, feature.c_str())) 277 return true; 278 } 279 280 if (throwIfNotExists) 281 TCU_THROW(NotSupportedError, "Feature " + feature + " is not supported"); 282 283 return false; 284 } 285 isDeviceFeatureInitialized(VkStructureType sType) const286 bool DeviceFeatures::isDeviceFeatureInitialized(VkStructureType sType) const 287 { 288 for (const auto f : m_features) 289 { 290 if (f->getFeatureDesc().sType == sType) 291 return true; 292 } 293 return false; 294 } 295 ~DeviceFeatures(void)296 DeviceFeatures::~DeviceFeatures(void) 297 { 298 for (auto p : m_features) 299 delete p; 300 301 m_features.clear(); 302 } 303 304 } // vk 305