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