• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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