• 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 *shadingRateImageFeatures = 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 					verifyFeatureAddCriteria(featureStructCreationData, deviceExtensionProperties))
106 				{
107 					FeatureStructWrapperBase *p = (*featureStructCreationData.creatorFunction)();
108 					if (p == DE_NULL)
109 						continue;
110 
111 					// if feature struct is part of VkPhysicalDeviceVulkan1{1,2,3}Features
112 					// we dont add it to the chain but store and fill later from blob data
113 					bool featureFilledFromBlob = false;
114 					if (vk12Supported)
115 					{
116 						deUint32 blobApiVersion = getBlobFeaturesVersion(p->getFeatureDesc().sType);
117 						if (blobApiVersion)
118 							featureFilledFromBlob = (apiVersion >= blobApiVersion);
119 					}
120 
121 					if (featureFilledFromBlob)
122 						featuresToFillFromBlob.push_back(p);
123 					else
124 					{
125 						VkStructureType structType = p->getFeatureDesc().sType;
126 						void *rawStructPtr = p->getFeatureTypeRaw();
127 
128 						if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT)
129 							robustness2Features = reinterpret_cast<VkPhysicalDeviceRobustness2FeaturesEXT *>(rawStructPtr);
130 						else if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES_EXT)
131 							imageRobustnessFeatures = reinterpret_cast<VkPhysicalDeviceImageRobustnessFeaturesEXT *>(rawStructPtr);
132 #ifndef CTS_USES_VULKANSC
133 						else if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR)
134 							fragmentShadingRateFeatures = reinterpret_cast<VkPhysicalDeviceFragmentShadingRateFeaturesKHR *>(rawStructPtr);
135 						else if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV)
136 							shadingRateImageFeatures = reinterpret_cast<VkPhysicalDeviceShadingRateImageFeaturesNV *>(rawStructPtr);
137 						else if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT)
138 							fragmentDensityMapFeatures = reinterpret_cast<VkPhysicalDeviceFragmentDensityMapFeaturesEXT *>(rawStructPtr);
139 						else if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PAGEABLE_DEVICE_LOCAL_MEMORY_FEATURES_EXT)
140 							pageableDeviceLocalMemoryFeatures = reinterpret_cast<VkPhysicalDevicePageableDeviceLocalMemoryFeaturesEXT *>(rawStructPtr);
141 						else if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MUTABLE_DESCRIPTOR_TYPE_FEATURES_EXT)
142 							mutableDescriptorTypeFeatures = reinterpret_cast<VkPhysicalDeviceMutableDescriptorTypeFeaturesEXT *>(rawStructPtr);
143 #endif // CTS_USES_VULKANSC
144 	   // add to chain
145 						*nextPtr = rawStructPtr;
146 						nextPtr = p->getFeatureTypeNext();
147 					}
148 					m_features.push_back(p);
149 				}
150 				else
151 				{
152 #ifndef CTS_USES_VULKANSC
153 					// Some non-standard promotions may need feature structs filled in anyway.
154 					if (!strcmp(featureName, "VK_EXT_extended_dynamic_state") && vk13Supported)
155 					{
156 						FeatureStructWrapperBase *p = (*featureStructCreationData.creatorFunction)();
157 						if (p == DE_NULL)
158 							continue;
159 
160 						auto f = reinterpret_cast<VkPhysicalDeviceExtendedDynamicStateFeaturesEXT *>(p->getFeatureTypeRaw());
161 						f->extendedDynamicState = true;
162 						m_features.push_back(p);
163 					}
164 					if (!strcmp(featureName, "VK_EXT_extended_dynamic_state2") && vk13Supported)
165 					{
166 						FeatureStructWrapperBase *p = (*featureStructCreationData.creatorFunction)();
167 						if (p == DE_NULL)
168 							continue;
169 
170 						auto f = reinterpret_cast<VkPhysicalDeviceExtendedDynamicState2FeaturesEXT *>(p->getFeatureTypeRaw());
171 						f->extendedDynamicState2 = true;
172 						m_features.push_back(p);
173 					}
174 #endif	// CTS_USES_VULKANSC
175 				}
176 			}
177 
178 			vki.getPhysicalDeviceFeatures2(physicalDevice, &m_coreFeatures2);
179 
180 			// fill data from VkPhysicalDeviceVulkan1{1,2,3}Features
181 			if (vk12Supported)
182 			{
183 				AllFeaturesBlobs allBlobs =
184 					{
185 						m_vulkan11Features,
186 						m_vulkan12Features,
187 #ifndef CTS_USES_VULKANSC
188 						m_vulkan13Features,
189 #endif // CTS_USES_VULKANSC
190 	   // add blobs from future vulkan versions here
191 					};
192 
193 				for (auto feature : featuresToFillFromBlob)
194 					feature->initializeFeatureFromBlob(allBlobs);
195 			}
196 		}
197 		else
198 			m_coreFeatures2.features = getPhysicalDeviceFeatures(vki, physicalDevice);
199 
200 		// 'enableAllFeatures' is used to create a complete list of supported features.
201 		if (!enableAllFeatures)
202 		{
203 			// Disable robustness by default, as it has an impact on performance on some HW.
204 			if (robustness2Features)
205 			{
206 				robustness2Features->robustBufferAccess2 = false;
207 				robustness2Features->robustImageAccess2 = false;
208 				robustness2Features->nullDescriptor = false;
209 			}
210 			if (imageRobustnessFeatures)
211 			{
212 				imageRobustnessFeatures->robustImageAccess = false;
213 			}
214 			m_coreFeatures2.features.robustBufferAccess = false;
215 
216 #ifndef CTS_USES_VULKANSC
217 			// Disable VK_EXT_fragment_density_map and VK_NV_shading_rate_image features
218 			// that must: not be enabled if KHR fragment shading rate features are enabled.
219 			if (fragmentShadingRateFeatures &&
220 				(fragmentShadingRateFeatures->pipelineFragmentShadingRate ||
221 				 fragmentShadingRateFeatures->primitiveFragmentShadingRate ||
222 				 fragmentShadingRateFeatures->attachmentFragmentShadingRate))
223 			{
224 				if (shadingRateImageFeatures)
225 					shadingRateImageFeatures->shadingRateImage = false;
226 				if (fragmentDensityMapFeatures)
227 					fragmentDensityMapFeatures->fragmentDensityMap = false;
228 			}
229 
230 			// Disable pageableDeviceLocalMemory by default since it may modify the behavior
231 			// of device-local, and even host-local, memory allocations for all tests.
232 			// pageableDeviceLocalMemory will use targetted testing on a custom device.
233 			if (pageableDeviceLocalMemoryFeatures)
234 				pageableDeviceLocalMemoryFeatures->pageableDeviceLocalMemory = false;
235 
236 			// Disable mutableDescriptorTypeFeatures by default because it can
237 			// impact performance on some hardware.
238 			if (mutableDescriptorTypeFeatures)
239 				mutableDescriptorTypeFeatures->mutableDescriptorType = false;
240 #endif // CTS_USES_VULKANSC
241 		}
242 	}
243 
verifyFeatureAddCriteria(const FeatureStructCreationData & item,const std::vector<VkExtensionProperties> & properties)244 	bool DeviceFeatures::verifyFeatureAddCriteria(const FeatureStructCreationData &item, const std::vector<VkExtensionProperties> &properties)
245 	{
246 #ifndef CTS_USES_VULKANSC
247 		if (deStringEqual(item.name, VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME))
248 		{
249 			for (const auto &property : properties)
250 			{
251 				if (deStringEqual(property.extensionName, item.name))
252 					return (property.specVersion == item.specVersion);
253 			}
254 		}
255 #else  // CTS_USES_VULKANSC
256 		DE_UNREF(item);
257 		DE_UNREF(properties);
258 #endif // CTS_USES_VULKANSC
259 
260 		return true;
261 	}
262 
contains(const std::string & feature,bool throwIfNotExists) const263 	bool DeviceFeatures::contains(const std::string &feature, bool throwIfNotExists) const
264 	{
265 		for (const auto f : m_features)
266 		{
267 			if (deStringEqual(f->getFeatureDesc().name, feature.c_str()))
268 				return true;
269 		}
270 
271 		if (throwIfNotExists)
272 			TCU_THROW(NotSupportedError, "Feature " + feature + " is not supported");
273 
274 		return false;
275 	}
276 
isDeviceFeatureInitialized(VkStructureType sType) const277 	bool DeviceFeatures::isDeviceFeatureInitialized(VkStructureType sType) const
278 	{
279 		for (const auto f : m_features)
280 		{
281 			if (f->getFeatureDesc().sType == sType)
282 				return true;
283 		}
284 		return false;
285 	}
286 
~DeviceFeatures(void)287 	DeviceFeatures::~DeviceFeatures(void)
288 	{
289 		for (auto p : m_features)
290 			delete p;
291 
292 		m_features.clear();
293 	}
294 
295 } // vk
296