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 VkPhysicalDeviceFragmentShadingRateFeaturesKHR* fragmentShadingRateFeatures = nullptr;
39 VkPhysicalDeviceShadingRateImageFeaturesNV* shadingRateImageFeatures = nullptr;
40 VkPhysicalDeviceFragmentDensityMapFeaturesEXT* fragmentDensityMapFeatures = nullptr;
41
42 m_coreFeatures2 = initVulkanStructure();
43 m_vulkan11Features = initVulkanStructure();
44 m_vulkan12Features = initVulkanStructure();
45
46 if (isInstanceExtensionSupported(apiVersion, instanceExtensions, "VK_KHR_get_physical_device_properties2"))
47 {
48 const std::vector<VkExtensionProperties> deviceExtensionProperties = enumerateDeviceExtensionProperties(vki, physicalDevice, DE_NULL);
49 void** nextPtr = &m_coreFeatures2.pNext;
50 std::vector<FeatureStructWrapperBase*> featuresToFillFromBlob;
51 bool vk12Supported = (apiVersion >= VK_MAKE_VERSION(1, 2, 0));
52
53 // in vk12 we have blob structures combining features of couple previously
54 // available feature structures, that now in vk12 must be removed from chain
55 if (vk12Supported)
56 {
57 addToChainVulkanStructure(&nextPtr, m_vulkan11Features);
58 addToChainVulkanStructure(&nextPtr, m_vulkan12Features);
59 }
60
61 // iterate over data for all feature that are defined in specification
62 for (const auto& featureStructCreationData : featureStructCreationArray)
63 {
64 const char* featureName = featureStructCreationData.name;
65
66 // check if this feature is available on current device
67 if (de::contains(deviceExtensions.begin(), deviceExtensions.end(), featureName) &&
68 verifyFeatureAddCriteria(featureStructCreationData, deviceExtensionProperties))
69 {
70 FeatureStructWrapperBase* p = (*featureStructCreationData.creatorFunction)();
71 if (p == DE_NULL)
72 continue;
73
74 // if feature struct is part of VkPhysicalDeviceVulkan1{1,2}Features
75 // we dont add it to the chain but store and fill later from blob data
76 bool featureFilledFromBlob = false;
77 if (vk12Supported)
78 featureFilledFromBlob = isPartOfBlobFeatures(p->getFeatureDesc().sType);
79
80 if (featureFilledFromBlob)
81 featuresToFillFromBlob.push_back(p);
82 else
83 {
84 VkStructureType structType = p->getFeatureDesc().sType;
85 void* rawStructPtr = p->getFeatureTypeRaw();
86
87 if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ROBUSTNESS_2_FEATURES_EXT)
88 robustness2Features = reinterpret_cast<VkPhysicalDeviceRobustness2FeaturesEXT*>(rawStructPtr);
89 else if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_ROBUSTNESS_FEATURES_EXT)
90 imageRobustnessFeatures = reinterpret_cast<VkPhysicalDeviceImageRobustnessFeaturesEXT*>(rawStructPtr);
91 else if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_SHADING_RATE_FEATURES_KHR)
92 fragmentShadingRateFeatures = reinterpret_cast<VkPhysicalDeviceFragmentShadingRateFeaturesKHR*>(rawStructPtr);
93 else if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SHADING_RATE_IMAGE_FEATURES_NV)
94 shadingRateImageFeatures = reinterpret_cast<VkPhysicalDeviceShadingRateImageFeaturesNV*>(rawStructPtr);
95 else if (structType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT)
96 fragmentDensityMapFeatures = reinterpret_cast<VkPhysicalDeviceFragmentDensityMapFeaturesEXT*>(rawStructPtr);
97
98 // add to chain
99 *nextPtr = rawStructPtr;
100 nextPtr = p->getFeatureTypeNext();
101 }
102 m_features.push_back(p);
103 }
104 }
105
106 vki.getPhysicalDeviceFeatures2(physicalDevice, &m_coreFeatures2);
107
108 // fill data from VkPhysicalDeviceVulkan1{1,2}Features
109 if (vk12Supported)
110 {
111 AllFeaturesBlobs allBlobs =
112 {
113 m_vulkan11Features,
114 m_vulkan12Features,
115 // add blobs from future vulkan versions here
116 };
117
118 for (auto feature : featuresToFillFromBlob)
119 feature->initializeFeatureFromBlob(allBlobs);
120 }
121 }
122 else
123 m_coreFeatures2.features = getPhysicalDeviceFeatures(vki, physicalDevice);
124
125 // 'enableAllFeatures' is used to create a complete list of supported features.
126 if (!enableAllFeatures)
127 {
128 // Disable robustness by default, as it has an impact on performance on some HW.
129 if (robustness2Features)
130 {
131 robustness2Features->robustBufferAccess2 = false;
132 robustness2Features->robustImageAccess2 = false;
133 robustness2Features->nullDescriptor = false;
134 }
135 if (imageRobustnessFeatures)
136 {
137 imageRobustnessFeatures->robustImageAccess = false;
138 }
139 m_coreFeatures2.features.robustBufferAccess = false;
140
141 // Disable VK_EXT_fragment_density_map and VK_NV_shading_rate_image features
142 // that must: not be enabled if KHR fragment shading rate features are enabled.
143 if (fragmentShadingRateFeatures &&
144 (fragmentShadingRateFeatures->pipelineFragmentShadingRate ||
145 fragmentShadingRateFeatures->primitiveFragmentShadingRate ||
146 fragmentShadingRateFeatures->attachmentFragmentShadingRate))
147 {
148 if (shadingRateImageFeatures)
149 shadingRateImageFeatures->shadingRateImage = false;
150 if (fragmentDensityMapFeatures)
151 fragmentDensityMapFeatures->fragmentDensityMap = false;
152 }
153 }
154 }
155
verifyFeatureAddCriteria(const FeatureStructCreationData & item,const std::vector<VkExtensionProperties> & properties)156 bool DeviceFeatures::verifyFeatureAddCriteria (const FeatureStructCreationData& item, const std::vector<VkExtensionProperties>& properties)
157 {
158 if (deStringEqual(item.name, VK_KHR_VULKAN_MEMORY_MODEL_EXTENSION_NAME))
159 {
160 for (const auto& property : properties)
161 {
162 if (deStringEqual(property.extensionName, item.name))
163 return (property.specVersion == item.specVersion);
164 }
165 }
166
167 return true;
168 }
169
contains(const std::string & feature,bool throwIfNotExists) const170 bool DeviceFeatures::contains (const std::string& feature, bool throwIfNotExists) const
171 {
172 for (const auto f : m_features)
173 {
174 if (deStringEqual(f->getFeatureDesc().name, feature.c_str()))
175 return true;
176 }
177
178 if (throwIfNotExists)
179 TCU_THROW(NotSupportedError, "Feature " + feature + " is not supported");
180
181 return false;
182 }
183
isDeviceFeatureInitialized(VkStructureType sType) const184 bool DeviceFeatures::isDeviceFeatureInitialized (VkStructureType sType) const
185 {
186 for (const auto f : m_features)
187 {
188 if (f->getFeatureDesc().sType == sType)
189 return true;
190 }
191 return false;
192 }
193
~DeviceFeatures(void)194 DeviceFeatures::~DeviceFeatures (void)
195 {
196 for (auto p : m_features)
197 delete p;
198
199 m_features.clear();
200 }
201
202 } // vk
203
204