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 uint32_t apiVersion,const VkPhysicalDevice physicalDevice,const std::vector<std::string> & instanceExtensions,const std::vector<std::string> & deviceExtensions,const bool enableAllFeatures)29 DeviceFeatures::DeviceFeatures(const InstanceInterface &vki, const uint32_t apiVersion,
30 const VkPhysicalDevice physicalDevice,
31 const std::vector<std::string> &instanceExtensions,
32 const std::vector<std::string> &deviceExtensions, const bool enableAllFeatures)
33 {
34 VkPhysicalDeviceRobustness2FeaturesEXT *robustness2Features = nullptr;
35 VkPhysicalDeviceImageRobustnessFeaturesEXT *imageRobustnessFeatures = nullptr;
36 #ifndef CTS_USES_VULKANSC
37 VkPhysicalDeviceFragmentShadingRateFeaturesKHR *fragmentShadingRateFeatures = nullptr;
38 VkPhysicalDeviceShadingRateImageFeaturesNV *shadingRateImageFeaturesNV = nullptr;
39 VkPhysicalDeviceFragmentDensityMapFeaturesEXT *fragmentDensityMapFeatures = nullptr;
40 VkPhysicalDevicePageableDeviceLocalMemoryFeaturesEXT *pageableDeviceLocalMemoryFeatures = nullptr;
41 VkPhysicalDeviceMutableDescriptorTypeFeaturesEXT *mutableDescriptorTypeFeatures = nullptr;
42 VkPhysicalDeviceLegacyDitheringFeaturesEXT *legacyDitheringFeatures = nullptr;
43 #endif // CTS_USES_VULKANSC
44
45 m_coreFeatures2 = initVulkanStructure();
46 m_vulkan11Features = initVulkanStructure();
47 m_vulkan12Features = initVulkanStructure();
48 #ifndef CTS_USES_VULKANSC
49 m_vulkan13Features = initVulkanStructure();
50 #endif // CTS_USES_VULKANSC
51 #ifdef CTS_USES_VULKANSC
52 m_vulkanSC10Features = initVulkanStructure();
53 #endif // CTS_USES_VULKANSC
54
55 if (isInstanceExtensionSupported(apiVersion, instanceExtensions, "VK_KHR_get_physical_device_properties2"))
56 {
57 const std::vector<VkExtensionProperties> deviceExtensionProperties =
58 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 uint32_t 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 =
139 reinterpret_cast<VkPhysicalDeviceImageRobustnessFeaturesEXT *>(rawStructPtr);
140 #ifndef CTS_USES_VULKANSC
141 else if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR)
142 fragmentShadingRateFeatures =
143 reinterpret_cast<VkPhysicalDeviceFragmentShadingRateFeaturesKHR *>(rawStructPtr);
144 else if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV)
145 shadingRateImageFeaturesNV =
146 reinterpret_cast<VkPhysicalDeviceShadingRateImageFeaturesNV *>(rawStructPtr);
147 else if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT)
148 fragmentDensityMapFeatures =
149 reinterpret_cast<VkPhysicalDeviceFragmentDensityMapFeaturesEXT *>(rawStructPtr);
150 else if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PAGEABLE_DEVICE_LOCAL_MEMORY_FEATURES_EXT)
151 pageableDeviceLocalMemoryFeatures =
152 reinterpret_cast<VkPhysicalDevicePageableDeviceLocalMemoryFeaturesEXT *>(rawStructPtr);
153 else if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT)
154 mutableDescriptorTypeFeatures =
155 reinterpret_cast<VkPhysicalDeviceMutableDescriptorTypeFeaturesEXT *>(rawStructPtr);
156 else if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LEGACY_DITHERING_FEATURES_EXT)
157 legacyDitheringFeatures =
158 reinterpret_cast<VkPhysicalDeviceLegacyDitheringFeaturesEXT *>(rawStructPtr);
159 #endif // CTS_USES_VULKANSC
160 // add to chain
161 *nextPtr = rawStructPtr;
162 nextPtr = p->getFeatureTypeNext();
163 }
164 m_features.push_back(p);
165 }
166 else
167 {
168 #ifndef CTS_USES_VULKANSC
169 // Some non-standard promotions may need feature structs filled in anyway.
170 if (!strcmp(featureName, "VK_EXT_extended_dynamic_state") &&
171 (de::contains(allDeviceExtensions.begin(), allDeviceExtensions.end(),
172 "VK_EXT_extended_dynamic_state")))
173 {
174 FeatureStructWrapperBase *p = (*featureStructCreationData.creatorFunction)();
175 if (p == DE_NULL)
176 continue;
177
178 auto f =
179 reinterpret_cast<VkPhysicalDeviceExtendedDynamicStateFeaturesEXT *>(p->getFeatureTypeRaw());
180 f->extendedDynamicState = true;
181 m_features.push_back(p);
182 }
183 if (!strcmp(featureName, "VK_EXT_extended_dynamic_state2") &&
184 (de::contains(allDeviceExtensions.begin(), allDeviceExtensions.end(),
185 "VK_EXT_extended_dynamic_state2")))
186 {
187 FeatureStructWrapperBase *p = (*featureStructCreationData.creatorFunction)();
188 if (p == DE_NULL)
189 continue;
190
191 auto f =
192 reinterpret_cast<VkPhysicalDeviceExtendedDynamicState2FeaturesEXT *>(p->getFeatureTypeRaw());
193 f->extendedDynamicState2 = true;
194 m_features.push_back(p);
195 }
196 #endif // CTS_USES_VULKANSC
197 }
198 }
199
200 vki.getPhysicalDeviceFeatures2(physicalDevice, &m_coreFeatures2);
201
202 // fill data from VkPhysicalDeviceVulkan1{1,2,3}Features
203 if (vk12Supported)
204 {
205 AllFeaturesBlobs allBlobs = {
206 m_vulkan11Features, m_vulkan12Features,
207 #ifndef CTS_USES_VULKANSC
208 m_vulkan13Features,
209 #endif // CTS_USES_VULKANSC
210 // add blobs from future vulkan versions here
211 };
212
213 for (auto feature : featuresToFillFromBlob)
214 feature->initializeFeatureFromBlob(allBlobs);
215 }
216 }
217 else
218 m_coreFeatures2.features = getPhysicalDeviceFeatures(vki, physicalDevice);
219
220 // 'enableAllFeatures' is used to create a complete list of supported features.
221 if (!enableAllFeatures)
222 {
223 // Disable robustness by default, as it has an impact on performance on some HW.
224 if (robustness2Features)
225 {
226 robustness2Features->robustBufferAccess2 = false;
227 robustness2Features->robustImageAccess2 = false;
228 robustness2Features->nullDescriptor = false;
229 }
230 if (imageRobustnessFeatures)
231 {
232 imageRobustnessFeatures->robustImageAccess = false;
233 }
234 m_coreFeatures2.features.robustBufferAccess = false;
235
236 #ifndef CTS_USES_VULKANSC
237 m_vulkan13Features.robustImageAccess = false;
238
239 // Disable VK_EXT_fragment_density_map and VK_NV_shading_rate_image features
240 // that must: not be enabled if KHR fragment shading rate features are enabled.
241 if (fragmentShadingRateFeatures && (fragmentShadingRateFeatures->pipelineFragmentShadingRate ||
242 fragmentShadingRateFeatures->primitiveFragmentShadingRate ||
243 fragmentShadingRateFeatures->attachmentFragmentShadingRate))
244 {
245 if (shadingRateImageFeaturesNV)
246 shadingRateImageFeaturesNV->shadingRateImage = false;
247 if (fragmentDensityMapFeatures)
248 fragmentDensityMapFeatures->fragmentDensityMap = false;
249 }
250
251 // Disable pageableDeviceLocalMemory by default since it may modify the behavior
252 // of device-local, and even host-local, memory allocations for all tests.
253 // pageableDeviceLocalMemory will use targetted testing on a custom device.
254 if (pageableDeviceLocalMemoryFeatures)
255 pageableDeviceLocalMemoryFeatures->pageableDeviceLocalMemory = false;
256
257 // Disable mutableDescriptorTypeFeatures by default because it can
258 // impact performance on some hardware.
259 if (mutableDescriptorTypeFeatures)
260 mutableDescriptorTypeFeatures->mutableDescriptorType = false;
261
262 // Disable legacyDitheringFeatures by default because it interacts with
263 // dynamic_rendering. On some hardware DR tests may fail on precision.
264 // Float thresholds would need to be more lenient for low bitrate formats
265 // when DR is used togehrt with legacy dithering.
266 if (legacyDitheringFeatures)
267 legacyDitheringFeatures->legacyDithering = false;
268 #endif // CTS_USES_VULKANSC
269 }
270 }
271
verifyFeatureAddCriteria(const FeatureStructCreationData & item,const std::vector<VkExtensionProperties> & properties)272 bool DeviceFeatures::verifyFeatureAddCriteria(const FeatureStructCreationData &item,
273 const std::vector<VkExtensionProperties> &properties)
274 {
275 #ifndef CTS_USES_VULKANSC
276 if (deStringEqual(item.name, VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME))
277 {
278 for (const auto &property : properties)
279 {
280 if (deStringEqual(property.extensionName, item.name))
281 return (property.specVersion == item.specVersion);
282 }
283 }
284 #else // CTS_USES_VULKANSC
285 DE_UNREF(item);
286 DE_UNREF(properties);
287 #endif // CTS_USES_VULKANSC
288
289 return true;
290 }
291
contains(const std::string & feature,bool throwIfNotExists) const292 bool DeviceFeatures::contains(const std::string &feature, bool throwIfNotExists) const
293 {
294 for (const auto f : m_features)
295 {
296 if (deStringEqual(f->getFeatureDesc().name, feature.c_str()))
297 return true;
298 }
299
300 if (throwIfNotExists)
301 TCU_THROW(NotSupportedError, "Feature " + feature + " is not supported");
302
303 return false;
304 }
305
isDeviceFeatureInitialized(VkStructureType sType) const306 bool DeviceFeatures::isDeviceFeatureInitialized(VkStructureType sType) const
307 {
308 for (const auto f : m_features)
309 {
310 if (f->getFeatureDesc().sType == sType)
311 return true;
312 }
313 return false;
314 }
315
~DeviceFeatures(void)316 DeviceFeatures::~DeviceFeatures(void)
317 {
318 for (auto p : m_features)
319 delete p;
320
321 m_features.clear();
322 }
323
324 } // namespace vk
325